JavaRush /Blog Java /Random-MS /REST API dan satu lagi tugas ujian.
Денис
Tahap
Киев

REST API dan satu lagi tugas ujian.

Diterbitkan dalam kumpulan
Bahagian I: Permulaan Di mana hendak bermula? Cukup aneh, tetapi dari spesifikasi teknikal. Adalah sangat penting untuk memastikan bahawa selepas membaca TOR yang diserahkan, anda memahami sepenuhnya apa yang tertulis di dalamnya dan apa yang diharapkan oleh pelanggan. Pertama, ini penting untuk pelaksanaan selanjutnya, dan kedua, jika anda tidak melaksanakan apa yang diharapkan daripada anda, ia tidak akan menguntungkan anda. Untuk mengelakkan pembaziran udara, mari kita lakarkan spesifikasi teknikal yang mudah. Jadi, saya mahukan perkhidmatan yang boleh saya hantar data, ia akan disimpan pada perkhidmatan dan dikembalikan kepada saya sesuka hati. Saya juga perlu boleh mengemas kini dan memadam data ini jika perlu . Beberapa ayat nampaknya tidak jelas, bukan? Bagaimanakah saya mahu menghantar data ke sana? Apakah teknologi yang hendak digunakan? Apakah format data ini? Juga tiada contoh data masuk dan keluar. Kesimpulan - spesifikasi teknikal sudah teruk . Mari cuba frasa semula: Kami memerlukan perkhidmatan yang boleh memproses permintaan HTTP dan berfungsi dengan data yang dipindahkan. Ini akan menjadi pangkalan data rekod kakitangan. Kami akan mempunyai pekerja, mereka dibahagikan mengikut jabatan dan kepakaran, pekerja mungkin mempunyai tugas yang diberikan kepada mereka. Tugas kami adalah untuk mengautomasikan proses perakaunan untuk pekerja yang diupah, dipecat, dipindahkan, serta proses penyerahan dan pembatalan tugas menggunakan API REST. Sebagai Fasa 1, kami kini hanya bekerja dengan pekerja. Perkhidmatan mesti mempunyai beberapa titik akhir untuk berfungsi dengannya: - POST /pekerja - Permintaan POST, yang mesti menerima objek JSON dengan data tentang pekerja. Objek ini mesti disimpan ke pangkalan data; jika objek sedemikian sudah wujud dalam pangkalan data, maklumat dalam medan mesti dikemas kini dengan data baharu. - GET /pekerja - Permintaan GET yang mengembalikan keseluruhan senarai pekerja yang disimpan dalam pangkalan data - DELETE - DELETE /pekerja untuk memadam model data pekerja pekerja tertentu:
{
  "firstName": String,
  "lastName": String,
  "department": String,
  "salary": String
  "hired": String //"yyyy-mm-dd"
  "tasks": [
  	//List of tasks, not needed for Phase 1
  ]
}
Bahagian II: Alat untuk kerja Jadi, skop kerja lebih kurang jelas, tetapi bagaimana kita akan melakukannya? Jelas sekali, tugasan sedemikian dalam ujian diberikan dengan beberapa matlamat aplikasi, untuk melihat cara anda mengekod, untuk memaksa anda menggunakan Spring dan bekerja sedikit dengan pangkalan data. Baiklah, mari kita lakukan ini. Kami memerlukan projek SpringBoot dengan sokongan REST API dan pangkalan data. Di tapak web https://start.spring.io/ anda boleh menemui semua yang anda perlukan. REST API atau tugas ujian lain.  - 1 Anda boleh memilih sistem binaan, bahasa, versi SpringBoot, tetapkan tetapan artifak, versi Java dan kebergantungan. Mengklik butang Tambah Ketergantungan akan memaparkan menu ciri dengan bar carian. Calon pertama untuk perkataan rehat dan data ialah Spring Web dan Spring Data - kami akan menambahkannya. Lombok ialah perpustakaan yang mudah yang membolehkan anda menggunakan anotasi untuk menyingkirkan kilometer kod dengan kaedah getter dan setter. Dengan mengklik butang Jana kami akan menerima arkib dengan projek yang sudah boleh dibongkar dan dibuka dalam IDE kegemaran kami. Secara lalai, kami akan menerima projek kosong, dengan fail konfigurasi untuk sistem binaan (dalam kes saya ia akan menjadi gradle, tetapi dengan perkara Maven tidak ada perbezaan asas, dan satu fail permulaan musim bunga) Orang yang penuh perhatian boleh memberi perhatian kepada dua REST API atau tugas ujian lain.  - 2 perkara . Pertama, saya mempunyai dua fail tetapan application.properties dan application.yml. Secara lalai, anda akan mendapat betul-betul sifat - fail kosong di mana anda boleh menyimpan tetapan, tetapi bagi saya format yml kelihatan sedikit lebih mudah dibaca, sekarang saya akan menunjukkan perbandingan: Walaupun fakta bahawa REST API atau tugas ujian lain.  - 3 gambar di sebelah kiri kelihatan lebih padat , adalah mudah untuk melihat sejumlah besar pertindihan dalam laluan sifat. Gambar di sebelah kanan adalah fail yml biasa dengan struktur pokok yang agak mudah dibaca. Saya akan menggunakan fail ini kemudian dalam projek. Perkara kedua yang mungkin diperhatikan oleh orang yang prihatin ialah projek saya sudah mempunyai beberapa pakej. Belum ada kod yang waras di sana, tetapi ia berbaloi untuk membacanya. Bagaimanakah permohonan ditulis? Mempunyai tugasan tertentu, kita mesti menguraikannya - pecahkannya kepada subtugas kecil dan mulakan pelaksanaannya yang konsisten. Apa yang dikehendaki daripada kita? Kami perlu menyediakan API yang boleh digunakan oleh pelanggan; kandungan pakej pengawal akan bertanggungjawab untuk bahagian fungsi ini. Bahagian kedua aplikasi ialah pangkalan data - pakej kegigihan. Di dalamnya kami akan menyimpan perkara seperti Entiti Pangkalan Data (Entiti) serta Repositori - antara muka spring khas yang membolehkan anda berinteraksi dengan pangkalan data. Pakej perkhidmatan akan mengandungi kelas perkhidmatan. Kami akan bercakap tentang perkhidmatan jenis Spring di bawah. Dan akhir sekali, pakej utils. Kelas utilitarian dengan semua jenis kaedah tambahan akan disimpan di sana, contohnya, kelas untuk bekerja dengan tarikh dan masa, atau kelas untuk bekerja dengan rentetan, dan siapa tahu apa lagi. Mari kita mula melaksanakan bahagian pertama fungsi. Bahagian III: Pengawal
@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());
    }
}
Kini kelas EmployeeController kami kelihatan seperti ini. Terdapat beberapa perkara penting yang patut diberi perhatian di sini. 1. Anotasi di atas kelas, @RestController pertama memberitahu aplikasi kami bahawa kelas ini akan menjadi titik akhir. 2. @RequestMapping, walaupun tidak wajib, adalah anotasi yang berguna; ia membolehkan anda menetapkan laluan khusus untuk titik akhir. Itu. untuk mengetuknya, anda perlu menghantar permintaan bukan ke localhost:port/employee, tetapi dalam kes ini ke localhost:8086/api/v1/employee Sebenarnya, dari mana datangnya api/v1 dan pekerja ini? Daripada application.yml kami Jika anda melihat dengan teliti, anda boleh menemui baris berikut di sana:
application:
  endpoint:
    root: api/v1
    employee: employee
    task: task
Seperti yang anda lihat, kami mempunyai pembolehubah seperti application.endpoint.root dan application.endpoint.employee, ini adalah apa yang saya tulis dalam anotasi, saya cadangkan untuk mengingati kaedah ini - ia akan menjimatkan banyak masa untuk mengembangkan atau menulis semula fungsi - ia sentiasa lebih mudah untuk mempunyai segala-galanya dalam config , dan bukan hardcode keseluruhan projek. 3. @RequiredArgsConstructor ialah anotasi Lombok, perpustakaan mudah yang membolehkan anda mengelak daripada menulis perkara yang tidak perlu. Dalam kes ini, anotasi adalah bersamaan dengan fakta bahawa kelas akan mempunyai pembina awam dengan semua medan ditandakan sebagai muktamad
public EmployeeController(EmployeeService employeeService) {
    this.employeeService=employeeService;
}
Tetapi mengapa kita perlu menulis perkara sedemikian jika satu anotasi sudah mencukupi? :) By the way, tahniah, medan akhir yang paling peribadi ini tidak lebih daripada Suntikan Ketergantungan yang terkenal. Mari kita teruskan, sebenarnya, apakah jenis bidang perkhidmatan pekerja? Ini akan menjadi salah satu perkhidmatan dalam projek kami yang akan memproses permintaan untuk titik akhir ini. Idea di sini sangat mudah. Setiap kelas harus mempunyai tugasnya sendiri dan tidak boleh dibebani dengan tindakan yang tidak perlu. Jika ini ialah pengawal, biarkan ia menguruskan menerima permintaan dan menghantar respons, tetapi kami lebih suka mempercayakan pemprosesan kepada perkhidmatan tambahan. Perkara terakhir yang tinggal dalam kelas ini ialah satu-satunya kaedah yang mengembalikan senarai semua pekerja syarikat kami menggunakan perkhidmatan yang dinyatakan di atas. Senarai itu sendiri dibungkus dalam entiti yang dipanggil ResponseEntity. Saya melakukan ini supaya pada masa hadapan, jika perlu, saya boleh dengan mudah mengembalikan kod respons dan mesej yang saya perlukan, yang boleh difahami oleh sistem automatik. Jadi, sebagai contoh, ResponseEntity.ok() akan mengembalikan kod ke-200, yang akan mengatakan bahawa semuanya baik-baik saja, tetapi jika saya kembali, sebagai contoh
return ResponseEntity.badRequest().body(Collections.emptyList());
maka pelanggan akan menerima kod 400 - bad reuqest dan senarai kosong dalam respons. Biasanya kod ini dikembalikan jika permintaan tidak betul. Tetapi satu pengawal tidak akan mencukupi untuk kami memulakan aplikasi. Kebergantungan kami tidak akan membenarkan kami melakukan ini, kerana kami masih mesti mempunyai asas :) Baiklah, mari kita beralih ke bahagian seterusnya. Bahagian IV: ketekunan mudah Memandangkan tugas utama kami adalah untuk melancarkan aplikasi, kami akan mengehadkan diri kami kepada beberapa stub buat masa ini. Anda telah melihat dalam kelas Pengawal bahawa kami mengembalikan senarai objek jenis Pekerja, ini akan menjadi entiti kami untuk pangkalan data. Mari kita buat dalam pakej demo.persistence.entity . Pada masa hadapan, pakej entiti boleh ditambah dengan entiti lain daripada pangkalan data.
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
}
Ini ialah kelas semudah pintu, Anotasi yang menyatakan dengan tepat seperti berikut: ini ialah entiti pangkalan data @Entity, ini ialah kelas dengan data @Data - Lombok. Lombok yang berguna akan mencipta untuk kita semua getter, setter, pembina yang diperlukan - pemadat lengkap. Nah, sedikit ceri pada kek ialah @Accessors(chain = true) Sebenarnya, ini adalah pelaksanaan tersembunyi corak Builder. Katakan anda mempunyai kelas dengan sekumpulan medan yang anda ingin tetapkan bukan melalui pembina, tetapi dengan kaedah. Dalam susunan yang berbeza, mungkin tidak semua pada masa yang sama. Anda tidak pernah tahu jenis logik yang akan ada dalam aplikasi anda. Anotasi ini adalah kunci anda untuk tugasan ini. Mari lihat:
public Employee createEmployee() {
    return new Employee().setName("Peter")
        				.setAge("28")
        				.setDepartment("IT");
}
Andaikan kita mempunyai semua bidang ini dalam kelas kita😄Anda boleh menetapkannya, anda tidak boleh menetapkannya, anda boleh mencampurkannya di tempat-tempat. Dalam kes hanya 3 hartanah, ini tidak kelihatan seperti sesuatu yang luar biasa. Tetapi terdapat kelas dengan bilangan sifat yang lebih besar, contohnya 50. Dan tulis sesuatu seperti
public Employee createEmployee() {
    return new Employee("Peter", "28", "IT", "single", "loyal", List.of(new Task("do Something 1"), new Task ("do Something 2")));
}
Nampak tak cantik sangat kan? Kita juga perlu mengikuti dengan ketat urutan menambah pembolehubah mengikut pembina. Walau bagaimanapun, saya menyimpang, mari kita kembali kepada intipati. Sekarang kita mempunyai satu medan (wajib) di dalamnya - pengecam unik. Dalam kes ini, ini ialah nombor jenis Panjang, yang dijana secara automatik apabila disimpan ke pangkalan data. Sehubungan itu, anotasi @Id jelas menunjukkan kepada kami bahawa ini adalah pengecam unik; @GeneratedValue bertanggungjawab untuk penjanaan uniknya. Perlu diingat bahawa @Id boleh ditambah pada medan yang tidak dijana secara automatik, tetapi kemudian isu keunikan perlu ditangani secara manual. Apakah yang boleh menjadi pengecam pekerja yang unik? Contohnya, nama penuh + jabatan... walau bagaimanapun, seseorang mempunyai nama penuh, dan ada kemungkinan mereka akan bekerja di jabatan yang sama, kecil, tetapi ada - itu bermakna keputusan itu tidak baik. Ia mungkin untuk menambah sekumpulan bidang lain, seperti tarikh sewa, bandar, tetapi semua ini, nampaknya saya, merumitkan logik terlalu banyak. Anda mungkin tertanya-tanya, bagaimana mungkin sekumpulan bidang menjadi unik sekaligus? Saya jawab - mungkin. Jika anda ingin tahu, anda boleh google tentang perkara seperti @Embeddable dan @Embedded Baiklah, kita sudah selesai dengan intipatinya. Sekarang kita memerlukan repositori mudah. Ia akan kelihatan seperti ini:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}
Ya, itu sahaja. Hanya antara muka, kami memanggilnya EmployeeRepository, ia memanjangkan JpaRepository yang mempunyai dua parameter yang ditaip, yang pertama bertanggungjawab untuk jenis data yang berfungsi dengannya, yang kedua untuk jenis kunci. Dalam kes kami, ini adalah Pekerja dan Long. Cukuplah setakat ini. Sentuhan terakhir sebelum melancarkan aplikasi ialah perkhidmatan kami:
@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public List<Employee> getAllEmployees() {
        return List.of(new Employee().setId(123L));
    }
}
Terdapat RequiredArgsConstructor yang sudah biasa dan anotasi @Service baharu - inilah yang biasanya menandakan lapisan logik perniagaan. Apabila menjalankan konteks musim bunga, kelas yang ditandai dengan anotasi ini akan dibuat sebagai Beans. Apabila dalam kelas EmployeeController kami telah mencipta harta akhir EmployeeService dan melampirkan RequiredArgsConstructor (atau mencipta pembina dengan tangan) Spring, apabila memulakan aplikasi, ia akan mencari tempat ini dan menyelitkan kami objek kelas ke dalam pembolehubah ini. Lalai di sini ialah Singleton - i.e. akan ada satu objek untuk semua pautan tersebut; ini penting untuk diambil kira semasa mereka bentuk aplikasi. Sebenarnya, itu sahaja, aplikasi itu boleh dilancarkan. Jangan lupa masukkan tetapan yang diperlukan dalam konfigurasi. REST API atau tugas ujian lain.  - 4 Saya tidak akan menerangkan cara memasang pangkalan data, mencipta pengguna dan pangkalan data itu sendiri, tetapi saya hanya akan ambil perhatian bahawa dalam URL saya menggunakan dua parameter tambahan - useUnicore=true dan characterEncoding=UTF-8. Ini dilakukan supaya teks akan dipaparkan lebih kurang sama pada mana-mana sistem. Walau bagaimanapun, jika anda terlalu malas untuk mengotak-atik pangkalan data dan benar-benar ingin mencari kod kerja, terdapat penyelesaian pantas: 1. Tambahkan kebergantungan berikut kepada build.gradle:
implementation 'com.h2database:h2:2.1.214'
2. Dalam application.yml anda perlu mengedit beberapa sifat, saya akan memberikan contoh lengkap bahagian spring untuk kesederhanaan:
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:
Pangkalan data akan disimpan dalam folder projek, dalam fail yang dipanggil mydb . Tetapi saya akan mengesyorkan memasang pangkalan data lengkap 😉 Artikel berguna mengenai topik: Spring Boot With H2 Database Untuk berjaga-jaga, saya akan menyediakan versi penuh build.gradle saya untuk menghapuskan percanggahan dalam kebergantungan:
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()
}
Sistem sedia untuk dilancarkan: REST API atau tugas ujian lain.  - 5 Anda boleh menyemaknya dengan menghantar permintaan GET daripada mana-mana program yang sesuai ke titik akhir kami. Dalam kes ini, penyemak imbas biasa akan melakukannya, tetapi pada masa hadapan kami memerlukan Posmen. REST API atau tugas ujian lain.  - 6 Ya, sebenarnya, kami belum lagi melaksanakan mana-mana keperluan perniagaan, tetapi kami sudah mempunyai aplikasi yang bermula dan boleh dikembangkan kepada fungsi yang diperlukan. Bersambung: API REST dan Pengesahan Data
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION