JavaRush /Java блогу /Random-KY /REST API жана башка сыноо тапшырмасы.
Денис
Деңгээл
Киев

REST API жана башка сыноо тапшырмасы.

Группада жарыяланган
I бөлүк: Баштоо Эмнеден баштоо керек? Кызык, бирок техникалык мүнөздөмөлөрдөн. Тапшырылган TOR менен таанышкандан кийин анда эмне жазылганын жана кардар эмнени күтөрүн толук түшүнгөнүңүзгө ынануу өтө маанилүү. Биринчиден, бул андан ары ишке ашыруу үчүн маанилүү, экинчиден, сизден күтүлгөн нерсени ишке ашырбасаңыз, бул сиздин пайдаңызга алып келбейт. Абаны текке кетирбөө үчүн, келгиле, жөнөкөй техникалык спецификацияны карап көрөлү. Ошентип, мен маалыматтарды жөнөтө турган кызматты каалайм, ал кызматта сакталып, мага каалагандай кайтарылып берилет. Керек болсо, мен дагы бул маалыматтарды жаңыртып, жок кыла алышым керек . Бир-эки сүйлөм так эмес окшойт, туурабы? Кантип мен ал жакка дайындарды жөнөткүм келет? Кандай технологияларды колдонуу керек? Бул маалымат кандай форматта болот? Кирүүчү жана чыгуучу маалыматтардын мисалдары да жок. Корутунду - техникалык мүнөздөмөлөрү мурунтан эле начар . Келгиле, кайталап айтууга аракет кылалы: Бизге HTTP сурамдарын иштете ала турган жана өткөрүлүп берилген маалыматтар менен иштей турган кызмат керек. Бул кадрларды эсепке алуу базасы болот. Бизде кызматкерлер болот, алар бөлүмдөр жана адистиктер боюнча бөлүнөт, кызматкерлердин аларга жүктөлгөн милдеттери болушу мүмкүн. Биздин милдет - REST API аркылуу жалданган, бошотулган, которулган кызматкерлерди эсепке алуу процессин, ошондой эле тапшырмаларды дайындоо жана жокко чыгаруу процессин автоматташтыруу. 1-фаза катары биз азыр жалаң кызматкерлер менен иштеп жатабыз. Кызматтын аны менен иштөө үчүн бир нече акыркы чекиттери болушу керек: - POST /кызматкер - POST сурамы, ал кызматкер жөнүндө маалыматтар менен JSON an objectисин кабыл алышы керек. Бул an object маалымат базасына сакталышы керек, эгерде мындай an object маалымат базасында мурунтан бар болсо, талаалардагы маалымат жаңы маалыматтар менен жаңыртылышы керек. - GET /employee - Маалыматтар базасында сакталган кызматкерлердин толук тизмесин кайтаруучу GET сурамы - DELETE - DELETE /employee белгилүү бир кызматкерди жок кылуу Кызматкерлердин маалымат модели:
{
  "firstName": String,
  "lastName": String,
  "department": String,
  "salary": String
  "hired": String //"yyyy-mm-dd"
  "tasks": [
  	//List of tasks, not needed for Phase 1
  ]
}
II бөлүк: Жумуш үчүн куралдар Ошентип, иштин көлөмү аздыр-көптүр түшүнүктүү, бирок биз муну кантип жасайбыз? Албетте, тесттеги мындай тапшырмалар бир нече колдонмо максаттары менен берилген, сиз кантип codeдогонуңузду көрүү үчүн, Жазды колдонууга жана маалымат базасы менен бир аз иштөөгө мажбурлоо. Мейли, муну кылалы. Бизге REST API колдоосу жана маалымат базасы бар SpringBoot долбоору керек. https://start.spring.io/ сайтында сизге керектүү нерселердин баарын таба аласыз. REST API же башка сыноо тапшырмасы.  - 1 Сиз куруу тутумун, тorн, SpringBoot versionсын, артефакт орнотууларын, Java versionсын жана көз карандылыкты тандай аласыз. Көз карандылыктарды кошуу баскычын чыкылdateу издөө тилкеси менен мүнөздүү менюну ачат. Эс алуу жана маалымат сөздөрүнө биринчи талапкерлер жазгы веб жана жазгы маалыматтар - биз аларды кошобуз. Lombok - бул сизге annotationларды колдонууга мүмкүндүк берүүчү ыңгайлуу китепкана, ал алуу жана сетер ыкмалары менен километрдик codeдон арылууга мүмкүндүк берет. Түзүү баскычын чыкылdateу менен биз долбоор менен архивди алабыз, аны мурунтан эле таңгактан чыгарып, сүйүктүү IDEде ачууга болот. Демейки боюнча, биз куруу тутумунун конфигурация файлы менен бош долбоорду алабыз (менин учурда ал gradle болот, бирок Maven менен эч кандай принципиалдуу айырма жок жана бир жазгы стартап файлы) REST API же башка сыноо тапшырмасы.  - 2 Кылдат адамдар эки нерсеге көңүл бурушу мүмкүн. . Биринчиден, менде application.properties жана application.yml эки орнотуу файлдары бар. Демейки боюнча, сиз так касиеттерге ээ болосуз - жөндөөлөрдү сактай турган бош файл, бирок мен үчүн yml форматы бир аз окула тургандай көрүнөт, азыр мен салыштырууну көрсөтөм: REST API же башка сыноо тапшырмасы.  - 3 Сол жактагы сүрөт компакттуураак көрүнгөнүнө карабастан , касиеттер жолунда көп сандагы кайталоону көрүү оңой. Оң жактагы сүрөт окууга оңой болгон дарак структурасы бар кадимки yml файлы. Мен бул файлды кийинчерээк долбоордо колдоном. Кылдат адамдар байкай турган экинчи нерсе - менин долбоордо бир нече пакеттер бар. Азырынча эч кандай акылга сыярлык code жок, бирок алар аркылуу өтүүгө арзырлык. Өтүнмө кантип жазылат? Белгилүү бир тапшырма болгондон кийин, биз аны майдалообуз керек - аны чакан субмилдеттерге бөлүп, аларды ырааттуу ишке ашырууну башташыбыз керек. Бизден эмне талап кылынат? Биз кардар колдоно турган API менен камсыз кылышыбыз керек; контроллер пакетинин мазмуну функциянын бул бөлүгү үчүн жооптуу болот. Тиркеменин экинчи бөлүгү маалымат базасы - туруктуулук пакети. Анда биз маалымат базасы менен өз ара аракеттенүүгө мүмкүндүк берүүчү атайын жазгы интерфейстер сыяктуу эле Маалыматтар базасынын an objectилери (an objectтери), ошондой эле репозиторийлер сыяктуу нерселерди сактайбыз. Кызмат пакети тейлөө класстарын камтыйт. Төмөндө Жаз түрү кызматы эмне жөнүндө сүйлөшөбүз. Жана акыркы, бирок жок дегенде, utils пакети. Ал жерде ар кандай жардамчы методдор менен утorтарлык класстар сакталат, мисалы, дата жана убакыт менен иштөө класстары же саптар менен иштөө класстары, дагы эмнени ким билет. Келгиле, функциянын биринчи бөлүгүн ишке ашыра баштайлы. III бөлүк: Башкаруучу
@RestController
@RequestMapping("${application.endpoint.root}")
@RequiredArgsConstructor
public class EmployeeController {

    private final EmployeeService employeeService;

    @GetMapping("${application.endpoint.employee}")
    public ResponseEntity<List<Employee>> getEmployees() {
        return ResponseEntity.ok().body(employeeService.getAllEmployees());
    }
}
Эми биздин EmployeeController классыбыз ушундай көрүнөт. Бул жерде көңүл бурууга арзырлык бир катар маанилүү нерселер бар. 1. Класстын үстүндөгү annotationлар, биринчи @RestController колдонмобузга бул класс акыркы чекит болорун айтат. 2. @RequestMapping, милдеттүү болбосо да, пайдалуу annotation болуп саналат, ал акыркы чекит үчүн белгилүү бир жолду коюуга мүмкүндүк берет. Ошол. аны тыкылdateу үчүн, сурамдарды localhost:port/employee эмес, бул учурда localhost:8086/api/v1/employee жөнөтүшүңүз керек. Чынында, бул api/v1 жана кызматкер кайдан келген? Биздин application.yml сайтынан кылдат карасаңыз, анда төмөнкү саптарды таба аласыз:
application:
  endpoint:
    root: api/v1
    employee: employee
    task: task
Көрүнүп тургандай, бизде application.endpoint.root жана application.endpoint.employee сыяктуу өзгөрмөлөр бар, булар annotationларда жазгандарым, мен бул ыкманы эстеп калууну сунуштайм - бул кеңейтүү же кайра жазууда көп убакытты үнөмдөйт. функционалдуулук - бүт долбоорду катуу codeдобостон, конфигурацияда бардыгын алуу дайыма ыңгайлуу. 3. @RequiredArgsConstructor бул Lombok annotationсы, керексиз нерселерди жазуудан качууга мүмкүндүк берген ыңгайлуу китепкана. Бул учурда, annotation класстын бардык талаалары акыркы деп белгиленген коомдук конструкторго ээ болгонуна барабар.
public EmployeeController(EmployeeService employeeService) {
    this.employeeService=employeeService;
}
Бирок, бир annotation жетиштүү болсо, эмне үчүн мындай жазуу керек? :) Баса, куттуктайбыз, бул эң купуя акыркы талаа - бул белгилүү көз карандылык инъекциясынан башка эч нерсе эмес. Келгиле, чындыгында, кызматкер Кызматы кандай тармак? Бул биздин долбоордогу ушул акыркы чекит боюнча сурамдарды иштете турган кызматтардын бири болот. Бул жерде идея абдан жөнөкөй. Ар бир класстын өзүнүн тапшырмасы болушу керек жана ашыкча керексиз аракеттер менен жүктөлбөшү керек. Эгер бул контролер болсо, ал суроо-талаптарды кабыл алуу жана жоопторду жөнөтүү менен алектенсин, бирок биз иштетүүнү кошумча кызматка тапшырганыбыз оң. Бул класста калган эң акыркы нерсе - бул жогоруда аталган кызматты колдонгон биздин компаниянын бардык кызматкерлеринин тизмесин кайтаруучу жалгыз ыкма. Тизме өзү ResponseEntity деп аталган an objectке оролгон. Мен муну келечекте, керек болсо, автоматташтырылган система түшүнө турган жооп codeун жана мага керектүү билдирүүнү оңой эле кайтарып алыш үчүн жасайм. Ошентип, мисалы, ResponseEntity.ok() 200-codeду кайтарат, ал баары жакшы деп айтат, бирок мен кайтып келсем, мисалы
return ResponseEntity.badRequest().body(Collections.emptyList());
анда кардар 400 codeун алат - bad reuqest жана жоопто бош тизме. Адатта, бул code эгер суроо туура эмес болсо, кайтарылат. Бирок колдонмону баштоо үчүн бизге бир контроллер жетишсиз. Биздин көз карандылыктарыбыз буга жол бербейт, анткени бизде дагы эле база болушу керек :) Келгиле, кийинки бөлүккө өтөбүз. IV бөлүк: жөнөкөй өжөрлүк Биздин негизги милдетибиз тиркемени ишке киргизүү болгондуктан, биз азырынча бир нече тактар ​​менен чектелебиз. Сиз Controller классында биз Кызматкер түрүндөгү an objectтердин тизмесин кайтарып жатканыбызды көрдүңүз, бул маалымат базасы үчүн биздин an object болот. Келгиле, аны demo.persistence.entity топтомунда түзөлү . Келечекте субъект пакети маалымат базасынан башка an objectтер менен толукталышы мүмкүн.
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
}
Бул эшик сыяктуу жөнөкөй класс, annotationлары так төмөндөгүлөрдү айтат: бул @Entity маалымат базасы, бул @Data - Lombok маалыматтары бар класс. Пайдалуу Ломбок биз үчүн бардык керектүү алгычтарды, орнотуучуларды, конструкторлорду - толук толтурууну жаратат. Мейли, торттун бир аз алчасы @Accessors(чынжыр = чындык) Чындыгында, бул Builder үлгүсүнүн жашыруун ишке ашырылышы. Сизде конструктор аркылуу эмес, методдор боюнча ыйгаргыңыз келген бир топ талаалары бар классыңыз бар дейли. Ар кандай тартипте, балким, баары бир эле учурда эмес. Колдонмоңузда кандай логика болорун эч качан билесиз. Бул annotation сиздин бул тапшырманын ачкычы болуп саналат. Кел карайбыз:
public Employee createEmployee() {
    return new Employee().setName("Peter")
        				.setAge("28")
        				.setDepartment("IT");
}
Классыбызда ушул талаалардын баары бар дейли😄Аларды дайындай аласыз, дайындай албайсыз, жерлерге аралаштырсаңыз болот. Болгону 3 касиетке келсек, бул укмуштуудай көрүнбөйт. Бирок бир топ көп сандагы касиеттери бар класстар бар, мисалы 50. Жана ушуга окшогон нерсени жаз
public Employee createEmployee() {
    return new Employee("Peter", "28", "IT", "single", "loyal", List.of(new Task("do Something 1"), new Task ("do Something 2")));
}
Абдан сулуу көрүнбөйт, туурабы? Биз ошондой эле конструкторго ылайык өзгөрмөлөрдү кошуу тартибин так сакташыбыз керек. Бирок, мен чегиндим, кепке кайталы. Азыр бизде бир (милдеттүү) талаа бар - уникалдуу идентификатор. Бул учурда, бул маалымат базасына сакталганда автоматтык түрдө түзүлө турган Узун типтеги номер. Демек, @Id annotationсы бул уникалдуу идентификатор экенин ачык көрсөтүп турат; @GeneratedValue анын уникалдуу жаралышы үчүн жооптуу. Белгилей кетчү нерсе, @Id автоматтык түрдө түзүлбөгөн талааларга кошсо болот, бирок андан кийин уникалдуулук маселеси кол менен чечorши керек. Кызматкердин уникалдуу идентификатору эмне болушу мүмкүн? Ооба, мисалы, толук аты-жөнү + бөлүм... бирок, адамдын толук фамorялары бар, алар бир бөлүмдө иштөө мүмкүнчүлүгү бар, кичинекей, бирок бар - бул чечим жаман дегенди билдирет. Ишке алынган датасы, шаары сыяктуу бир топ башка тармактарды кошсо болот эле, бирок мунун баары, менимче, логиканы өтө эле татаалдаштырат. Сиз кызыктырышы мүмкүн, ал тургай, бир тутам талаалар бир эле учурда уникалдуу болушу мүмкүн? Мен жооп берем - балким. Эгер сизди кызыктырсаңыз, @Embeddable жана @Embedded сыяктуу нерселер жөнүндө Google'да издесеңиз болот. Эми бизге жөнөкөй репозиторий керек. Ал мындай болот:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}
Ооба, баары ушул. Жөн гана интерфейс, биз аны EmployeeRepository деп атадык, ал эки терилген параметри бар JpaRepository кеңейтет, биринчиси ал иштеген маалымат түрүнө, экинчиси ачкыч түрүнө жооп берет. Биздин учурда, бул Кызматкер жана Узак. Азырынча ошол жетиштүү. Колдонмону ишке киргизүүдөн мурун акыркы тийүү биздин кызмат болот:
@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public List<Employee> getAllEmployees() {
        return List.of(new Employee().setId(123L));
    }
}
Буга чейин тааныш RequiredArgsConstructor жана жаңы @Service annotationсы бар - бул адатта бизнес логикалык катмарын билдирет. Жазгы контекстти иштеткенде, бул annotation менен белгиленген класстар буурчак катары түзүлөт. EmployeeController классында биз EmployeeService акыркы касиетин түзүп, RequiredArgsConstructor тиркелген (же конструкторду кол менен түзгөн) Spring, тиркемени инициализациялоодо, ал бул жерди таап, бизге класс an objectисин ушул өзгөрмөгө киргизет. Бул жерде демейки Singleton болуп саналат - б.а. бардык ушундай шилтемелер үчүн бир an object болот, бул колдонмону иштеп чыгууда эске алуу маанилүү. Чынында, бул баары, колдонмону ишке киргизүүгө болот. Конфигурацияга керектүү орнотууларды киргизүүнү унутпаңыз. REST API же башка сыноо тапшырмасы.  - 4 Мен маалымат базасын кантип орнотууну, колдонуучуну жана маалымат базасын кантип түзүү керектигин сүрөттөбөйм, бирок мен жөн гана URL'де мен эки кошумча параметрди колдоном - useUnicore=true жана characterEncoding=UTF-8. Бул текст каалаган системада аздыр-көптүр бирдей көрсөтүлүшү үчүн жасалган. Бирок, эгер сиз маалымат базасы менен иштөөгө жалкоо болсоңуз жана чындап эле жумушчу codeду тегеректегиңиз келсе, анда тез чечим бар: 1. build.gradleге төмөнкү көз карандылыкты кошуңуз:
implementation 'com.h2database:h2:2.1.214'
2. application.yml ичинде сиз бир нече касиеттерди түзөтүшүңүз керек, мен жөнөкөйлүк үчүн жазгы бөлүмдүн толук мисалын берем:
spring:
  application:
    name: "employee-management-service"
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
    database-platform: org.hibernate.dialect.H2Dialect
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:file:./mydb
    username: sa
    password:
Маалымат базасы долбоордун папкасында, mydb деп аталган файлда сакталат . Бирок мен толук кандуу маалымат базасын орнотууну сунуштайт элем 😉 Тема боюнча пайдалуу макала: H2 маалымат базасы менен жазгы жүктөө Болгондо, көз карандылыктагы келишпестиктерди жоюу үчүн build.gradle файлымдын толук versionсын берем:
plugins {
	id 'org.springframework.boot' version '2.7.2'
	id 'io.spring.dependency-management' version '1.0.12.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'mysql:mysql-connector-java:8.0.30'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}
Система ишке кирүүгө даяр: REST API же башка сыноо тапшырмасы.  - 5 Сиз аны биздин акыркы чекитке каалаган ылайыктуу программадан GET өтүнүчүн жөнөтүү менен текшере аласыз. Бул учурда, кадимки браузер жасайт, бирок келечекте бизге Почтачы керек болот. REST API же башка сыноо тапшырмасы.  - 6 Ооба, чындыгында, биз бизнес талаптарынын бирин да ишке ашыра элекпиз, бирок бизде мурунтан эле башталган жана талап кылынган функцияга чейин кеңейтorши мүмкүн болгон тиркеме бар. Уландысы: REST API жана Маалыматтарды текшерүү
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION