JavaRush /Java блогы /Random-KK /REST API және басқа сынақ тапсырмасы.
Денис
Деңгей
Киев

REST API және басқа сынақ тапсырмасы.

Топта жарияланған
I бөлім: Бастау Неден бастау керек? Бір қызығы, бірақ техникалық сипаттамалардан. Ұсынылған TOR-ны оқығаннан кейін сіз онда не жазылғанын және клиент не күтетінін толық түсінетініңізге көз жеткізу өте маңызды. Біріншіден, бұл әрі қарай жүзеге асыру үшін маңызды, екіншіден, сіз өзіңізден күткенді жүзеге асырмасаңыз, бұл сізге пайда әкелмейді. Ауаны ысырап етпеу үшін қарапайым техникалық сипаттаманы сызып көрейік. Сонымен, мен деректерді жібере алатын қызметті қалаймын, ол қызметте сақталады және өз қалауым бойынша маған қайтарылады. Сондай-ақ, қажет болса, бұл деректерді жаңарту және жою мүмкіндігі болуы керек . Бір-екі сөйлем анық емес сияқты, солай ма? Онда деректерді қалай жібергім келеді? Қандай технологияларды қолдану керек? Бұл деректер қандай форматта болады? Сондай-ақ кіріс және шығыс деректердің мысалдары жоқ. Қорытынды - техникалық сипаттама қазірдің өзінде нашар . Басқаша айтып көрейік: HTTP сұрауларын өңдей алатын және жіберілген деректермен жұмыс істей алатын қызмет қажет. Бұл персоналды есепке алу деректер базасы болады. Бізде қызметкерлер болады, олар бөлімдер мен мамандықтар бойынша бөлінген, қызметкерлердің оларға жүктелген міндеттері болуы мүмкін. Біздің міндетіміз - REST API көмегімен жұмысқа қабылданған, жұмыстан босатылған, ауыстырылған қызметкерлерді есепке алу процесін, сондай-ақ тапсырмаларды тағайындау және жою процесін автоматтандыру. 1-кезең ретінде біз қазір тек қызметкерлермен жұмыс істеп жатырмыз. Қызметте онымен жұмыс істеу үшін бірнеше соңғы нүктелер болуы керек: - POST /қызметкер - POST сұрауы, ол қызметкер туралы деректері бар JSON нысанын қабылдауы керек. Бұл нысан дерекқорда сақталуы керек, егер мұндай нысан дерекқорда бұрыннан бар болса, өрістердегі ақпарат жаңа деректермен жаңартылуы керек. - 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
  ]
}
ІІ бөлім: Жұмысқа арналған құралдар Сонымен, жұмыс көлемі азды-көпті анық, бірақ біз оны қалай жасаймыз? Әлбетте, тесттегі мұндай тапсырмалар бірнеше қолданбалы мақсаттармен беріледі, олар codeты қалай қолданатыныңызды көру, көктемді пайдалануға және дерекқормен аздап жұмыс істеуге мәжбүрлеу. Ал, мұны істейік. Бізге REST API қолдауы және дерекқоры бар SpringBoot жобасы қажет. Https://start.spring.io/ веб-сайтында сіз өзіңізге қажет нәрсені таба аласыз. REST API немесе басқа сынақ тапсырмасы.  - 1 Құрастыру жүйесін, тілін, SpringBoot нұсқасын таңдауға, артефакт параметрлерін, Java нұсқасын және тәуелділіктерді орнатуға болады. «Тәуелділіктерді қосу» түймесін басу іздеу жолағы бар сипаттамалық мәзірді шығарады. Демалыс және деректер сөздеріне алғашқы үміткерлер көктемгі веб және көктемгі деректер - біз оларды қосамыз. Lombok - бұл Getter және Setter әдістерімен километрлік codeтан құтылу үшін annotationларды пайдалануға мүмкіндік беретін ыңғайлы кітапхана. «Жасау» түймесін басу арқылы біз жобамен мұрағатты аламыз, оны қазірдің өзінде орамнан шығаруға және сүйікті IDE-де ашуға болады. Әдепкі бойынша, біз құрастыру жүйесіне арналған конфигурация файлы бар бос жобаны аламыз (менің жағдайда бұл gradle болады, бірақ Maven-де ештеңе түбегейлі айырмашылығы жоқ және бір көктемгі іске қосу файлы) REST API немесе басқа сынақ тапсырмасы.  - 2 Мұқият адамдар екі нәрсеге назар аудара алады. . Біріншіден, менде application.properties және application.yml параметрлерінің екі файлы бар. Әдепкі бойынша, сіз дәл сипаттарды аласыз - параметрлерді сақтауға болатын бос файл, бірақ маған yml пішімі біршама оқылатын болып көрінеді, енді мен салыстыруды көрсетемін: REST API немесе басқа сынақ тапсырмасы.  - 3 Сол жақтағы сурет ықшам болып көрінгеніне қарамастан , сипаттар жолында қайталанудың үлкен көлемін көру оңай. Оң жақтағы сурет - оқуға оңай ағаш құрылымы бар кәдімгі yml файлы. Мен бұл файлды кейінірек жобада қолданамын. Мұқият адамдар байқайтын екінші нәрсе - менің жобамда бірнеше пакеттер бар. Онда әлі дұрыс code жоқ, бірақ олар арқылы өту керек. Өтініш қалай жазылады? Белгілі бір тапсырмаға ие бола отырып, біз оны бөлшектеуіміз керек - оны кішігірім қосалқы тапсырмаларға бөліп, оларды дәйекті орындауды бастау керек. Бізден не талап етіледі? Біз клиент пайдалана алатын API қамтамасыз етуіміз керек; контроллер бумасының мазмұны функционалдылықтың осы бөлігіне жауапты болады. Қолданбаның екінші бөлігі мәліметтер базасы – тұрақтылық пакеті. Онда біз дерекқор нысандары (нұсқалары), сондай-ақ репозиторийлер сияқты нәрселерді сақтаймыз - дерекқормен өзара әрекеттесуге мүмкіндік беретін арнайы серіппелі интерфейстер. Қызметтер пакетінде қызмет көрсету сыныптары болады. Төменде көктемгі қызмет түрі туралы айтатын боламыз. Және соңғы, бірақ кем дегенде, 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 болып табылады, ол соңғы нүкте үшін арнайы жолды орнатуға мүмкіндік береді. Анау. оны қағу үшін сізге сұрауларды 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 — Ломбок annotationсы, қажетсіз нәрселерді жазудан аулақ болуға мүмкіндік беретін ыңғайлы кітапхана. Бұл жағдайда annotation сыныптың барлық өрістері түпкілікті деп белгіленген жалпы конструкторы болатынына баламалы.
public EmployeeController(EmployeeService employeeService) {
    this.employeeService=employeeService;
}
Бірақ бір annotation жеткілікті болса, неге мұндайды жазуымыз керек? :) Айтпақшы, құттықтаймыз, бұл ең жеке соңғы өріс атышулы тәуелділік инъекциясынан басқа ештеңе емес. Әрі қарай жүрейік, шын мәнінде, қызметкер қызметі қандай сала? Бұл осы соңғы нүктеге сұрауларды өңдейтін жобамыздағы қызметтердің бірі болады. Мұндағы идея өте қарапайым. Әр сыныптың өз тапсырмасы болуы керек және қажетсіз әрекеттермен шамадан тыс жүктелмеуі керек. Егер бұл контроллер болса, ол сұрауларды қабылдау және жауаптарды жіберумен айналыссын, бірақ өңдеуді қосымша қызметке тапсырғанымыз жөн. Бұл сыныпта қалған соңғы нәрсе - жоғарыда аталған қызметті пайдаланатын компаниямыздың барлық қызметкерлерінің тізімін қайтаратын жалғыз әдіс. Тізімнің өзі ResponseEntity деп аталатын нысанға оралған. Мен мұны болашақта қажет болған жағдайда автоматтандырылған жүйе түсінетін жауап codeы мен хабарламаны оңай қайтару үшін жасаймын. Мәселен, мысалы, ResponseEntity.ok() 200-ші codeты қайтарады, ол бәрі жақсы екенін айтады, бірақ мен қайтарсам, мысалы
return ResponseEntity.badRequest().body(Collections.emptyList());
содан кейін клиент 400 codeын алады - bad reuqest және жауапта бос тізім. Әдетте бұл code сұрау дұрыс емес болса қайтарылады. Бірақ қолданбаны іске қосу үшін бір контроллер жеткіліксіз. Біздің тәуелділіктеріміз мұны істеуге мүмкіндік бермейді, өйткені бізде әлі де база болуы керек :) Ал, келесі бөлікке көшейік. IV бөлім: қарапайым табандылық Біздің негізгі міндетіміз қолданбаны іске қосу болғандықтан, біз әзірше бірнеше тікемен шектелеміз. Сіз Controller сыныбында біз Employee түріндегі нысандар тізімін қайтаратынымызды көрдіңіз, бұл дерекқорға арналған біздің нысанымыз болады. Оны demo.persistence.entity бумасында жасайық Болашақта нысан бумасын дерекқордағы басқа нысандармен толықтыруға болады.
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
}
Бұл есік сияқты қарапайым класс, оның Аннотациялары дәл мынаны айтады: бұл @Entity дерекқор нысаны, бұл @Data - Lombok деректері бар сынып. Пайдалы 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 автоматты түрде жасалмайтын өрістерге қосылуы мүмкін екенін атап өткен жөн, бірақ содан кейін бірегейлік мәселесін қолмен шешу қажет болады. Қызметкердің бірегей идентификаторы қандай болуы мүмкін? Жақсы, мысалы, толық аты-жөні + бөлім... дегенмен, адамның толық аты бар, олардың бір бөлімде жұмыс істеу мүмкіндігі бар, шағын, бірақ бар - бұл шешім нашар дегенді білдіреді. Жұмысқа алынған күн, қала сияқты басқа да көптеген өрістерді қосуға болады, бірақ мұның бәрі, менің ойымша, логиканы тым қиындатады. Сіз таң қалуыңыз мүмкін, қалайша бір топ өрістердің бірден бірегей болуы мүмкін? Мен жауап беремін - мүмкін. Егер сізді қызықтыратын болсаңыз, @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мен белгіленген сыныптар Beans ретінде жасалады. EmployeeController сыныбында біз соңғы EmployeeService қасиетін жасаған кезде және RequiredArgsConstructor (немесе конструкторды қолмен жасаған) Spring тіркеген кезде, қолданбаны инициализациялау кезінде ол осы орынды тауып, осы айнымалыға сынып нысанын жібереді. Мұнда әдепкі - Singleton - яғни. барлық осындай сілтемелер үшін бір нысан болады, бұл қолданбаны құрастыру кезінде ескеру маңызды. Іс жүзінде, бұл бәрі, қолданбаны іске қосуға болады. Конфигурацияда қажетті параметрлерді енгізуді ұмытпаңыз. 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 файлының толық нұсқасын ұсынамын:
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 сұрауын жіберу арқылы тексеруге болады. Бұл жағдайда қарапайым браузер жасайды, бірақ болашақта бізге Postman қажет болады. REST API немесе басқа сынақ тапсырмасы.  - 6 Иә, шын мәнінде, біз бизнес талаптарының ешқайсысын әлі орындаған жоқпыз, бірақ бізде іске қосылатын және қажетті функционалдылыққа дейін кеңейтілуі мүмкін қолданба бар. Жалғасы: REST API және деректерді тексеру
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION