JavaRush /Java blogi /Random-UZ /REST API va boshqa sinov vazifasi.
Денис
Daraja
Киев

REST API va boshqa sinov vazifasi.

Guruhda nashr etilgan
I qism: Boshlanish Qayerdan boshlash kerak? G'alati, lekin texnik xususiyatlardan. Taqdim etilgan TORni o'qib chiqqandan so'ng, unda nima yozilganligini va mijoz nimani kutayotganini to'liq tushunganingizga ishonch hosil qilish juda muhimdir. Birinchidan, bu keyingi amalga oshirish uchun muhim, ikkinchidan, sizdan kutilgan narsani amalga oshirmasangiz, bu sizning foydangizga bo'lmaydi. Havoni isrof qilmaslik uchun oddiy texnik xususiyatlarni chizamiz. Shunday qilib, men ma'lumotlarni yuborishim mumkin bo'lgan xizmatni xohlayman, u xizmatda saqlanadi va xohlaganimcha menga qaytariladi. Agar kerak bo'lsa, men ham ushbu ma'lumotlarni yangilash va o'chirish imkoniyatiga ega bo'lishim kerak . Bir-ikki jumla aniq narsaga o'xshamaydi, to'g'rimi? Qanday qilib u yerga ma'lumotlarni yuborishni xohlayman? Qanday texnologiyalardan foydalanish kerak? Ushbu ma'lumotlar qanday formatda bo'ladi? Shuningdek, kiruvchi va chiquvchi ma'lumotlarga misollar yo'q. Xulosa - texnik xususiyatlar allaqachon yomon . Keling, takrorlashga harakat qilaylik: Bizga HTTP so'rovlarini qayta ishlay oladigan va uzatilgan ma'lumotlar bilan ishlaydigan xizmat kerak. Bu kadrlar ma'lumotlar bazasi bo'ladi. Bizda xodimlar bo'ladi, ular bo'limlar va mutaxassisliklar bo'yicha bo'linadi, xodimlarning ularga yuklangan vazifalari bo'lishi mumkin. Bizning vazifamiz ishga qabul qilingan, ishdan bo'shatilgan, o'tkazilgan xodimlarni hisobga olish jarayonini, shuningdek, REST API yordamida vazifalarni belgilash va bekor qilish jarayonini avtomatlashtirishdir. 1-bosqich sifatida biz hozirda faqat xodimlar bilan ishlayapmiz. Xizmat u bilan ishlash uchun bir nechta so'nggi nuqtalarga ega bo'lishi kerak: - POST /xodim - POST so'rovi, u xodim haqidagi ma'lumotlarga ega JSON ob'ektini qabul qilishi kerak. Ushbu ob'ekt ma'lumotlar bazasida saqlanishi kerak, agar bunday ob'ekt ma'lumotlar bazasida mavjud bo'lsa, maydonlardagi ma'lumotlar yangi ma'lumotlar bilan yangilanishi kerak. - GET /employee - Ma'lumotlar bazasida saqlangan xodimlarning to'liq ro'yxatini qaytaradigan GET so'rovi - DELETE - DELETE /employee ma'lum bir xodimni o'chirish uchun Xodimlar ma'lumotlari modeli:
{
  "firstName": String,
  "lastName": String,
  "department": String,
  "salary": String
  "hired": String //"yyyy-mm-dd"
  "tasks": [
  	//List of tasks, not needed for Phase 1
  ]
}
II qism: Ish uchun asboblar Demak, ish doirasi ko'proq yoki kamroq aniq, lekin biz buni qanday qilamiz? Shubhasiz, testdagi bunday topshiriqlar bir nechta dastur maqsadlari bilan berilgan, ular qanday kodlanganligini ko'rish, sizni Spring-dan foydalanishga va ma'lumotlar bazasi bilan biroz ishlashga majbur qilish. Xo'sh, buni qilaylik. Bizga REST API yordami va ma'lumotlar bazasi bilan SpringBoot loyihasi kerak. https://start.spring.io/ veb-saytida sizga kerak bo'lgan hamma narsani topishingiz mumkin. REST API yoki boshqa sinov vazifasi.  - 1 Qurilish tizimini, tilni, SpringBoot versiyasini tanlashingiz, artefakt sozlamalarini, Java versiyasini va bog'liqliklarni o'rnatishingiz mumkin. Bog'liqlarni qo'shish tugmasini bosish qidiruv paneli bilan xarakterli menyuni ochadi. Dam olish va ma'lumotlar so'zlari uchun birinchi nomzodlar - Spring Web va Spring Data - biz ularni qo'shamiz. Lombok - bu getter va setter usullari bilan kilometrlik kodlardan xalos bo'lish uchun izohlardan foydalanish imkonini beruvchi qulay kutubxona. "Yaratish" tugmasini bosish orqali biz loyiha bilan arxivni olamiz, uni allaqachon ochish va sevimli IDE-da ochish mumkin. Odatiy bo'lib, biz qurish tizimi uchun konfiguratsiya fayli bo'lgan bo'sh loyihani olamiz (mening holimda bu gradle bo'ladi, lekin Maven bilan narsalar tubdan farq qilmaydi va bitta bahor ishga tushirish fayli) REST API yoki boshqa sinov vazifasi.  - 2 Diqqatli odamlar ikkita narsaga e'tibor berishlari mumkin edi. . Birinchidan, menda application.properties va application.yml ikkita sozlamalar fayli bor. Odatiy bo'lib, siz aniq xususiyatlarni olasiz - sozlamalarni saqlashingiz mumkin bo'lgan bo'sh fayl, lekin men uchun yml formati biroz o'qilishi mumkin ko'rinadi, endi men taqqoslashni ko'rsataman: REST API yoki boshqa sinov vazifasi.  - 3 Chapdagi rasm yanada ixcham ko'rinishiga qaramay , xususiyatlar yo'lida katta miqdordagi takrorlashni ko'rish oson. O'ngdagi rasm oddiy yml fayli bo'lib, uni o'qish juda oson bo'lgan daraxt tuzilmasi mavjud. Men ushbu faylni keyinchalik loyihada ishlataman. Ehtiyotkor odamlar sezishi mumkin bo'lgan ikkinchi narsa - mening loyihamda allaqachon bir nechta paketlar mavjud. U erda hali aqlli kod yo'q, lekin ular orqali o'tishga arziydi. Ariza qanday yoziladi? Muayyan vazifaga ega bo'lgan holda, biz uni qismlarga ajratishimiz kerak - uni kichik kichik vazifalarga ajratishimiz va ularni izchil amalga oshirishni boshlashimiz kerak. Bizdan nima talab qilinadi? Biz mijoz foydalanishi mumkin bo'lgan API taqdim etishimiz kerak; kontroller paketining mazmuni funksionallikning ushbu qismi uchun javobgar bo'ladi. Ilovaning ikkinchi qismi ma'lumotlar bazasi - qat'iylik paketi. Unda biz ma'lumotlar bazasi ob'ektlari (ob'ektlari), shuningdek, omborlar - ma'lumotlar bazasi bilan o'zaro aloqa qilish imkonini beruvchi maxsus bahor interfeyslari kabi narsalarni saqlaymiz. Xizmatlar paketi xizmat sinflarini o'z ichiga oladi. Bahor turi xizmati nima haqida quyida gaplashamiz. Va nihoyat, utils to'plami. Har xil yordamchi usullarga ega bo'lgan utilitar sinflar u erda saqlanadi, masalan, sana va vaqt bilan ishlash sinflari yoki satrlar bilan ishlash uchun sinflar va yana nima borligini kim biladi. Funktsionallikning birinchi qismini amalga oshirishni boshlaylik. III qism: boshqaruvchi
@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());
    }
}
Endi bizning EmployeeController sinfimiz shunday ko'rinadi. Bu erda e'tibor berishga arziydigan bir qator muhim narsalar mavjud. 1. Sinf ustidagi izohlar, birinchi @RestController ilovamizga bu sinf so'nggi nuqta bo'lishini aytadi. 2. @RequestMapping, garchi majburiy bo'lmasa ham, foydali izoh bo'lib, so'nggi nuqta uchun maxsus yo'lni o'rnatish imkonini beradi. Bular. uni taqillatish uchun siz so'rovlarni localhost:port/employee-ga emas, balki bu holda localhost:8086/api/v1/employee-ga yuborishingiz kerak. Aslida, bu api/v1 va xodim qayerdan kelgan? Application.yml saytimizdan diqqat bilan qarasangiz, u yerda quyidagi qatorlarni topishingiz mumkin:
application:
  endpoint:
    root: api/v1
    employee: employee
    task: task
Ko'rib turganingizdek, bizda application.endpoint.root va application.endpoint.employee kabi o'zgaruvchilar bor, men izohlarda aynan shunday yozganman, men ushbu usulni eslab qolishni maslahat beraman - bu kengaytirish yoki qayta yozishda ko'p vaqtni tejaydi. funksionallik - konfiguratsiyada hamma narsaga ega bo'lish har doim qulayroqdir va butun loyihani qattiq kodlash emas. 3. @RequiredArgsConstructor - Lombok annotatsiyasi, keraksiz narsalarni yozishdan qochish imkonini beruvchi qulay kutubxona. Bunday holda, izoh sinfda barcha maydonlar yakuniy deb belgilangan umumiy konstruktorga ega bo'lishiga tengdir.
public EmployeeController(EmployeeService employeeService) {
    this.employeeService=employeeService;
}
Lekin bitta izoh yetarli bo'lsa, nega bunday narsani yozishimiz kerak? :) Aytgancha, tabriklayman, bu eng shaxsiy yakuniy maydon mashhur qaramlik inyeksiyasidan boshqa narsa emas. Keling, davom etaylik, aslida, staffeService qanday soha? Bu bizning loyihamizdagi ushbu so'nggi nuqta uchun so'rovlarni ko'rib chiqadigan xizmatlardan biri bo'ladi. Bu erda fikr juda oddiy. Har bir sinf o'z vazifasiga ega bo'lishi kerak va keraksiz harakatlar bilan ortiqcha yuklanmasligi kerak. Agar bu nazoratchi bo'lsa, u so'rovlarni qabul qilish va javoblarni jo'natish bilan shug'ullansin, lekin biz qayta ishlashni qo'shimcha xizmatga ishonib topshirgan ma'qul. Ushbu sinfda qolgan oxirgi narsa - yuqorida aytib o'tilgan xizmatdan foydalangan holda kompaniyamizning barcha xodimlarining ro'yxatini qaytaradigan yagona usul. Ro'yxatning o'zi ResponseEntity deb nomlangan ob'ektga o'ralgan. Men buni kelajakda, agar kerak bo'lsa, avtomatlashtirilgan tizim tushuna oladigan javob kodini va xabarni osongina qaytarishim uchun qilaman. Shunday qilib, masalan, ResponseEntity.ok() 200-kodni qaytaradi, bu hamma narsa yaxshi ekanligini aytadi, lekin agar men qaytsam, masalan
return ResponseEntity.badRequest().body(Collections.emptyList());
keyin mijoz 400 kodini oladi - bad reuqest va javobda bo'sh ro'yxat. Odatda, so'rov noto'g'ri bo'lsa, bu kod qaytariladi. Ammo dasturni ishga tushirish uchun bitta kontroller etarli bo'lmaydi. Bizning qaramliklarimiz buni amalga oshirishga imkon bermaydi, chunki biz hali ham bazaga ega bo'lishimiz kerak :) Xo'sh, keling, keyingi qismga o'tamiz. IV qism: oddiy qat'iylik Bizning asosiy vazifamiz dasturni ishga tushirish bo'lganligi sababli, biz hozircha bir nechta qoralamalar bilan cheklanamiz. Siz allaqachon Controller sinfida biz Employee tipidagi ob'ektlar ro'yxatini qaytarishimizni ko'rgansiz, bu ma'lumotlar bazasi uchun bizning ob'ektimiz bo'ladi. Keling, uni demo.persistence.entity paketida yarataylik.Kelajakda ob'ekt paketi ma'lumotlar bazasidan boshqa ob'ektlar bilan to'ldirilishi mumkin.
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
}
Bu eshik kabi oddiy sinf bo'lib, uning Izohlari aynan quyidagilarni aytadi: bu @Entity ma'lumotlar bazasi ob'ekti, bu @Data - Lombok ma'lumotlariga ega sinf. Foydali Lombok biz uchun barcha kerakli oluvchilar, sozlagichlar, konstruktorlarni yaratadi - to'liq to'ldirish. Xo'sh, tort ustida bir oz olcha @Accessors (zanjir = rost) Aslida, bu Builder naqshining yashirin amalga oshirilishi. Aytaylik, sizda konstruktor orqali emas, balki usullar bo'yicha tayinlamoqchi bo'lgan bir qator maydonlar mavjud. Turli xil tartibda, ehtimol hammasi bir vaqtning o'zida emas. Sizning arizangizda qanday mantiq bo'lishini hech qachon bilmaysiz. Ushbu izoh bu vazifani hal qilish uchun kalit hisoblanadi. Keling, qaraylik:
public Employee createEmployee() {
    return new Employee().setName("Peter")
        				.setAge("28")
        				.setDepartment("IT");
}
Faraz qilaylik, bizning sinfimizda bu sohalarning barchasi mavjud😄Siz ularni belgilashingiz mumkin, ularni tayinlay olmaysiz, ularni joylarda aralashtirib yuborishingiz mumkin. Faqat 3 ta xususiyatga kelsak, bu ajoyib narsaga o'xshamaydi. Lekin xossalari ancha ko'p bo'lgan sinflar bor, masalan, 50. Va shunga o'xshash narsalarni yozing
public Employee createEmployee() {
    return new Employee("Peter", "28", "IT", "single", "loyal", List.of(new Task("do Something 1"), new Task ("do Something 2")));
}
Juda chiroyli ko'rinmaydi, shunday emasmi? Shuningdek, konstruktorga mos ravishda o'zgaruvchilarni qo'shish tartibiga qat'iy rioya qilishimiz kerak. Biroq, men chekinaman, keling, mavzuga qaytaylik. Endi bizda bitta (majburiy) maydon mavjud - noyob identifikator. Bunday holda, bu ma'lumotlar bazasiga saqlanganida avtomatik ravishda yaratiladigan Long tipidagi raqam. Shunga ko'ra, @Id izohi bizga bu noyob identifikator ekanligini aniq ko'rsatadi; @GeneratedValue uning noyob yaratilishi uchun javobgardir. Shuni ta'kidlash kerakki, @Id avtomatik ravishda yaratilmaydigan maydonlarga qo'shilishi mumkin, ammo keyin noyoblik masalasini qo'lda hal qilish kerak bo'ladi. Noyob xodim identifikatori nima bo'lishi mumkin? Xo'sh, masalan, to'liq ism + bo'lim ... ammo, odamning to'liq ismlari bor va ular bir xil bo'limda ishlash imkoniyati bor, kichik, lekin bor - bu qaror yomon degan ma'noni anglatadi. Ishga olingan sana, shahar kabi bir qancha boshqa sohalarni qo'shish mumkin edi, ammo bularning barchasi, menimcha, mantiqni juda murakkablashtiradi. Siz hayron bo'lishingiz mumkin, qanday qilib bir nechta maydonlar bir vaqtning o'zida noyob bo'lishi mumkin? Men javob beraman - ehtimol. Agar qiziqsangiz, @Embeddable va @Embedded kabi narsalar haqida Google orqali qidirishingiz mumkin. Endi bizga oddiy ombor kerak. Bu shunday ko'rinadi:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}
Ha, hammasi shu. Shunchaki interfeys, biz uni EmployeeRepository deb nomladik, u ikkita parametrga ega JpaRepository-ni kengaytiradi, birinchisi u ishlaydigan ma'lumotlar turiga, ikkinchisi kalit turiga javob beradi. Bizning holatlarimizda bular Xodim va Uzoq. Hozircha bu yetarli. Ilovani ishga tushirishdan oldin oxirgi teginish bizning xizmatimiz bo'ladi:
@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public List<Employee> getAllEmployees() {
        return List.of(new Employee().setId(123L));
    }
}
Allaqachon tanish bo'lgan RequiredArgsConstructor va yangi @Service izohi mavjud - bu odatda biznes mantiqiy qatlamini bildiradi. Bahor konteksti ishga tushirilganda, ushbu izoh bilan belgilangan sinflar Beans sifatida yaratiladi. EmployeeController sinfida biz EmployeeService yakuniy xususiyatini yaratganimizda va RequiredArgsConstructor (yoki qo'lda konstruktor yaratgan) Spring ilovasini biriktirganimizda, dasturni ishga tushirishda u shu joyni topadi va bizga sinf ob'ektini ushbu o'zgaruvchiga kiritadi. Bu erda sukut bo'yicha Singleton - ya'ni. barcha bunday havolalar uchun bitta ob'ekt bo'ladi, bu ilovani loyihalashda e'tiborga olish muhimdir. Aslida, bu hammasi, dasturni ishga tushirish mumkin. Konfiguratsiyada kerakli sozlamalarni kiritishni unutmang. REST API yoki boshqa sinov vazifasi.  - 4 Men ma'lumotlar bazasini qanday o'rnatishni, foydalanuvchini va ma'lumotlar bazasini qanday yaratishni tasvirlamayman, lekin shuni ta'kidlaymanki, URL manzilida men ikkita qo'shimcha parametrdan foydalanaman - useUnicore=true va characterEncoding=UTF-8. Bu matn har qanday tizimda ko'proq yoki kamroq teng ko'rsatilishi uchun qilingan. Biroq, agar siz ma'lumotlar bazasi bilan ishlashga dangasa bo'lsangiz va haqiqatan ham ishchi kodni aylanib chiqmoqchi bo'lsangiz, tezkor yechim bor: 1. build.gradle ga quyidagi bog'liqlikni qo'shing:
implementation 'com.h2database:h2:2.1.214'
2. Application.yml da siz bir nechta xususiyatlarni tahrirlashingiz kerak, soddalik uchun bahor bo'limiga to'liq misol keltiraman:
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:
Ma'lumotlar bazasi loyiha papkasida mydb deb nomlangan faylda saqlanadi . Ammo men to'liq ma'lumotlar bazasini o'rnatishni tavsiya qilaman 😉 Mavzu bo'yicha foydali maqola: H2 ma'lumotlar bazasi bilan bahor yuklash Har qanday holatda, bog'liqliklardagi tafovutlarni bartaraf etish uchun build.gradle-ning to'liq versiyasini taqdim etaman:
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()
}
Tizim ishga tushirishga tayyor: REST API yoki boshqa sinov vazifasi.  - 5 uni istalgan mos dasturdan so'nggi nuqtaga GET so'rovini yuborish orqali tekshirishingiz mumkin. Bunday holda, oddiy brauzer ishlaydi, ammo kelajakda bizga Postman kerak bo'ladi. REST API yoki boshqa sinov vazifasi.  - 6 Ha, aslida biz biznes talablaridan hech birini amalga oshirmadik, lekin bizda allaqachon ishga tushadigan va kerakli funksionallikka kengaytirilishi mumkin bo'lgan ilova mavjud. Davomi: REST API va Data Validation
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION