JavaRush /Java Blog /Random-ID /REST API dan tugas pengujian lainnya.
Денис
Level 37
Киев

REST API dan tugas pengujian lainnya.

Dipublikasikan di grup Random-ID
Bagian I: Awal Mulai dari mana? Anehnya, tapi dari spesifikasi teknisnya. Sangat penting untuk memastikan bahwa setelah membaca TOR yang dikirimkan Anda memahami sepenuhnya apa yang tertulis di dalamnya dan apa yang diharapkan klien. Pertama, hal ini penting untuk implementasi lebih lanjut, dan kedua, jika Anda tidak menerapkan apa yang diharapkan dari Anda, hal ini tidak akan menguntungkan Anda. Untuk menghindari pemborosan udara, mari kita buat sketsa spesifikasi teknis sederhana. Jadi, saya ingin layanan tempat saya dapat mengirim data, itu akan disimpan di layanan tersebut dan dikembalikan kepada saya sesuka hati. Saya juga harus bisa memperbarui dan menghapus data ini jika perlu . Beberapa kalimat sepertinya tidak jelas, bukan? Bagaimana caranya saya ingin mengirim data ke sana? Teknologi apa yang digunakan? Dalam format apa data ini akan digunakan? Juga tidak ada contoh data masuk dan keluar. Kesimpulan - spesifikasi teknisnya sudah buruk . Mari kita coba ulangi: Kita memerlukan layanan yang dapat memproses permintaan HTTP dan bekerja dengan data yang ditransfer. Ini akan menjadi database catatan personel. Kami akan memiliki karyawan, mereka dibagi berdasarkan departemen dan spesialisasi, karyawan mungkin memiliki tugas yang diberikan kepada mereka. Tugas kita adalah mengotomatiskan proses akuntansi untuk karyawan yang direkrut, dipecat, dipindahkan, serta proses penugasan dan pembatalan tugas menggunakan REST API. Sebagai Tahap 1, saat ini kami hanya bekerja dengan karyawan. Layanan harus memiliki beberapa titik akhir untuk bekerja dengannya: - POST /karyawan - Permintaan POST, yang harus menerima objek JSON dengan data tentang karyawan tersebut. Objek ini harus disimpan ke database, jika objek tersebut sudah ada di database, informasi di kolom harus diperbarui dengan data baru. - GET /employee - Permintaan GET yang mengembalikan seluruh daftar karyawan yang disimpan dalam database - DELETE - DELETE /employee untuk menghapus karyawan tertentu Model data karyawan:
{
  "firstName": String,
  "lastName": String,
  "department": String,
  "salary": String
  "hired": String //"yyyy-mm-dd"
  "tasks": [
  	//List of tasks, not needed for Phase 1
  ]
}
Bagian II: Alat untuk melakukan pekerjaan Jadi, ruang lingkup pekerjaannya kurang lebih jelas, namun bagaimana kita akan melakukannya? Jelas sekali, tugas-tugas seperti itu dalam pengujian diberikan dengan beberapa tujuan aplikasi, untuk melihat cara Anda membuat kode, untuk memaksa Anda menggunakan Spring dan untuk bekerja sedikit dengan database. Baiklah, mari kita lakukan ini. Kami memerlukan proyek SpringBoot dengan dukungan REST API dan database. Di situs web https://start.spring.io/ Anda dapat menemukan semua yang Anda butuhkan. REST API atau tugas pengujian lainnya.  - 1 Anda dapat memilih sistem build, bahasa, versi SpringBoot, mengatur pengaturan artefak, versi Java, dan dependensi. Mengklik tombol Tambah Ketergantungan akan memunculkan menu karakteristik dengan bilah pencarian. Kandidat pertama untuk kata rest dan data adalah Spring Web dan Spring Data - kami akan menambahkannya. Lombok adalah perpustakaan praktis yang memungkinkan Anda menggunakan anotasi untuk menghilangkan beberapa kilometer kode dengan metode pengambil dan penyetel. Dengan mengklik tombol Hasilkan kita akan menerima arsip dengan proyek yang sudah dapat dibongkar dan dibuka di IDE favorit kita. Secara default, kami akan menerima proyek kosong, dengan file konfigurasi untuk sistem build (dalam kasus saya ini akan menjadi gradle, tetapi dengan Maven tidak ada perbedaan mendasar, dan satu file startup pegas) Orang yang penuh perhatian dapat memperhatikan dua REST API atau tugas pengujian lainnya.  - 2 hal . Pertama, saya memiliki dua file pengaturan application.properties dan application.yml. Secara default, Anda akan mendapatkan properti - file kosong tempat Anda dapat menyimpan pengaturan, tetapi bagi saya format yml terlihat sedikit lebih mudah dibaca, sekarang saya akan menunjukkan perbandingannya: Meskipun gambar REST API atau tugas pengujian lainnya.  - 3 di sebelah kiri terlihat lebih kompak , mudah untuk melihat banyak duplikasi di jalur properti. Gambar sebelah kanan adalah file yml biasa dengan struktur pohon yang cukup mudah dibaca. Saya akan menggunakan file ini nanti di proyek. Hal kedua yang mungkin diperhatikan oleh orang-orang yang penuh perhatian adalah bahwa proyek saya sudah memiliki beberapa paket. Belum ada kode yang masuk akal di sana, tetapi ada baiknya untuk mempelajarinya. Bagaimana aplikasi ditulis? Memiliki tugas tertentu, kita harus menguraikannya - memecahnya menjadi subtugas kecil dan mulai menerapkannya secara konsisten. Apa yang dituntut dari kita? Kita perlu menyediakan API yang dapat digunakan klien; isi paket pengontrol akan bertanggung jawab atas bagian fungsionalitas ini. Bagian kedua dari aplikasi ini adalah database - paket persistensi. Di dalamnya kami akan menyimpan hal-hal seperti Entitas Basis Data (Entitas) serta Repositori - antarmuka pegas khusus yang memungkinkan Anda berinteraksi dengan basis data. Paket layanan akan berisi kelas layanan. Kami akan berbicara tentang apa itu Layanan tipe Pegas di bawah ini. Dan yang terakhir, paket utils. Kelas utilitarian dengan segala macam metode tambahan akan disimpan di sana, misalnya, kelas untuk bekerja dengan tanggal dan waktu, atau kelas untuk bekerja dengan string, dan entah apa lagi. Mari kita mulai mengimplementasikan bagian pertama dari fungsi tersebut. Bagian III: Pengendali
@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());
    }
}
Sekarang kelas EmployeeController kita terlihat seperti ini. Ada beberapa hal penting yang patut diperhatikan di sini. 1. Anotasi di atas kelas, @RestController pertama memberi tahu aplikasi kita bahwa kelas ini akan menjadi titik akhir. 2. @RequestMapping, meskipun tidak wajib, merupakan anotasi yang berguna; memungkinkan Anda menyetel jalur spesifik untuk titik akhir. Itu. untuk melakukannya, Anda perlu mengirim permintaan bukan ke localhost:port/employee, tetapi dalam kasus ini ke localhost:8086/api/v1/employee Sebenarnya, dari mana api/v1 dan karyawan ini berasal? Dari application.yml kami Jika Anda perhatikan lebih dekat, Anda dapat menemukan baris berikut di sana:
application:
  endpoint:
    root: api/v1
    employee: employee
    task: task
Seperti yang Anda lihat, kami memiliki variabel seperti application.endpoint.root dan application.endpoint.employee, inilah yang saya tulis di anotasi, saya sarankan mengingat metode ini - ini akan menghemat banyak waktu untuk memperluas atau menulis ulang fungsionalitas - selalu lebih nyaman untuk memiliki semuanya di konfigurasi, dan tidak melakukan hardcode pada keseluruhan proyek. 3. @RequiredArgsConstructor adalah anotasi Lombok, perpustakaan praktis yang memungkinkan Anda menghindari penulisan hal-hal yang tidak perlu. Dalam hal ini, anotasinya setara dengan fakta bahwa kelas tersebut akan memiliki konstruktor publik dengan semua bidang ditandai sebagai final
public EmployeeController(EmployeeService employeeService) {
    this.employeeService=employeeService;
}
Tetapi mengapa kita harus menulis hal seperti itu jika satu anotasi saja sudah cukup? :) Ngomong-ngomong, selamat, bidang terakhir yang paling pribadi ini tidak lebih dari Injeksi Ketergantungan yang terkenal kejam. Mari kita lanjutkan, sebenarnya bidang apa itu EmployeeService? Ini akan menjadi salah satu layanan dalam proyek kami yang akan memproses permintaan untuk titik akhir ini. Idenya di sini sangat sederhana. Setiap kelas harus memiliki tugasnya sendiri dan tidak boleh dibebani dengan tindakan yang tidak perlu. Jika ini adalah pengontrol, biarkan ia menangani penerimaan permintaan dan pengiriman respons, tetapi kami lebih suka mempercayakan pemrosesannya ke layanan tambahan. Hal terakhir yang tersisa di kelas ini adalah satu-satunya metode yang mengembalikan daftar semua karyawan perusahaan kami yang menggunakan layanan yang disebutkan di atas. Daftar itu sendiri dibungkus dalam sebuah entitas yang disebut ResponseEntity. Saya melakukan ini agar di masa mendatang, jika perlu, saya dapat dengan mudah mengembalikan kode respons dan pesan yang saya perlukan, yang dapat dipahami oleh sistem otomatis. Jadi misalnya ResponseEntity.ok() akan mengembalikan kode ke-200 yang mengatakan semuanya baik-baik saja tetapi jika saya kembali, misalnya
return ResponseEntity.badRequest().body(Collections.emptyList());
maka klien akan menerima kode 400 - permintaan buruk dan daftar kosong sebagai respons. Biasanya kode ini dikembalikan jika permintaan salah. Namun satu pengontrol tidak akan cukup bagi kita untuk memulai aplikasi. Ketergantungan kita tidak memungkinkan kita melakukan ini, karena kita masih harus memiliki basis :) Baiklah, mari kita lanjutkan ke bagian berikutnya. Bagian IV: ketekunan sederhana Karena tugas utama kami adalah meluncurkan aplikasi, kami akan membatasi diri pada beberapa rintisan untuk saat ini. Anda telah melihat di kelas Controller bahwa kami mengembalikan daftar objek bertipe Karyawan, ini akan menjadi entitas kami untuk database. Mari kita buat di paket demo.persistence.entity , kedepannya paket entitas dapat dilengkapi dengan entitas lain dari database.
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
}
Ini adalah kelas yang sederhana seperti pintu, Anotasinya berbunyi sebagai berikut: ini adalah entitas database @Entity, ini adalah kelas dengan data @Data - Lombok. Lombok yang membantu akan menciptakan bagi kita semua pengambil, penyetel, konstruktor yang diperlukan - isian lengkap. Nah, sedikit ceri pada kuenya adalah @Accessors(chain = true) Sebenarnya, ini adalah implementasi tersembunyi dari pola Builder. Misalkan Anda memiliki kelas dengan banyak bidang yang ingin Anda tetapkan bukan melalui konstruktor, tetapi berdasarkan metode. Dalam urutan yang berbeda, mungkin tidak semuanya sekaligus. Anda tidak pernah tahu logika seperti apa yang ada dalam aplikasi Anda. Anotasi ini adalah kunci Anda untuk tugas ini. Mari lihat:
public Employee createEmployee() {
    return new Employee().setName("Peter")
        				.setAge("28")
        				.setDepartment("IT");
}
Anggap saja kita punya semua bidang ini di kelas😄Anda dapat menetapkannya, Anda tidak dapat menetapkannya, Anda dapat mencampurkannya di beberapa tempat. Dalam kasus hanya 3 properti, ini sepertinya bukan sesuatu yang luar biasa. Tetapi ada kelas dengan jumlah properti yang jauh lebih banyak, misalnya 50. Dan tuliskan 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")));
}
Tidak terlihat cantik, bukan? Kita juga harus benar-benar mengikuti urutan penambahan variabel sesuai dengan konstruktornya. Namun, saya ngelantur, mari kembali ke pokok permasalahan. Sekarang kita memiliki satu bidang (wajib) di dalamnya - pengidentifikasi unik. Dalam hal ini, ini adalah nomor tipe Panjang, yang dihasilkan secara otomatis saat disimpan ke database. Oleh karena itu, anotasi @Id dengan jelas menunjukkan kepada kami bahwa ini adalah pengidentifikasi unik; @GeneratedValue bertanggung jawab atas pembuatan uniknya. Perlu dicatat bahwa @Id dapat ditambahkan ke bidang yang tidak dibuat secara otomatis, tetapi masalah keunikan perlu ditangani secara manual. Apa yang bisa menjadi pengenal unik karyawan? Nah, misalnya nama lengkap + departemen... namun, seseorang memiliki nama lengkap, dan ada kemungkinan mereka akan bekerja di departemen yang sama, kecil, tetapi ada - itu berarti keputusannya buruk. Dimungkinkan untuk menambahkan banyak bidang lain, seperti tanggal perekrutan, kota, tetapi semua ini, menurut saya, terlalu memperumit logika. Anda mungkin bertanya-tanya, bagaimana mungkin sekelompok bidang menjadi unik sekaligus? Saya menjawab - mungkin. Kalau penasaran bisa googling yang namanya @Embeddable dan @Embedded Nah, sudah selesai intinya. Sekarang kita membutuhkan repositori sederhana. Ini akan terlihat seperti ini:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}
Ya, itu saja. Hanya sebuah antarmuka, kami menyebutnya EmployeeRepository, ini memperluas JpaRepository yang memiliki dua parameter yang diketik, yang pertama bertanggung jawab atas tipe data yang digunakannya, yang kedua untuk tipe kunci. Dalam kasus kami, ini adalah Employee dan Long. Itu sudah cukup untuk saat ini. Sentuhan terakhir sebelum meluncurkan aplikasi adalah layanan kami:
@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public List<Employee> getAllEmployees() {
        return List.of(new Employee().setId(123L));
    }
}
Ada RequiredArgsConstructor yang sudah familiar dan anotasi @Service baru - inilah yang biasanya menunjukkan lapisan logika bisnis. Saat menjalankan konteks pegas, kelas yang ditandai dengan anotasi ini akan dibuat sebagai Beans. Ketika di kelas EmployeeController kita telah membuat properti akhir EmployeeService dan melampirkan RequiredArgsConstructor (atau membuat konstruktor dengan tangan) Spring, saat menginisialisasi aplikasi, ia akan menemukan tempat ini dan memasukkan objek kelas ke dalam variabel ini. Defaultnya di sini adalah Singleton - mis. akan ada satu objek untuk semua tautan tersebut; hal ini penting untuk dipertimbangkan saat merancang aplikasi. Sebenarnya itu saja, aplikasi sudah bisa diluncurkan. Jangan lupa untuk memasukkan pengaturan yang diperlukan di konfigurasi. REST API atau tugas pengujian lainnya.  - 4 Saya tidak akan menjelaskan cara menginstal database, membuat pengguna dan database itu sendiri, tetapi saya hanya akan mencatat bahwa di URL saya menggunakan dua parameter tambahan - useUnicore=true dan characterEncoding=UTF-8. Hal ini dilakukan agar teks dapat ditampilkan kurang lebih sama pada sistem apa pun. Namun, jika Anda terlalu malas untuk mengotak-atik database dan benar-benar ingin melihat-lihat kode yang berfungsi, ada solusi cepatnya: 1. Tambahkan dependensi berikut ke build.gradle:
implementation 'com.h2database:h2:2.1.214'
2. Di application.yml Anda perlu mengedit beberapa properti, saya akan memberikan contoh lengkap bagian pegas 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:
Basis data akan disimpan dalam folder proyek, dalam file bernama mydb . Tapi saya akan merekomendasikan menginstal database lengkap 😉 Artikel bermanfaat tentang topik: Spring Boot Dengan Database H2 Untuk berjaga-jaga, saya akan menyediakan versi lengkap build.gradle saya untuk menghilangkan perbedaan dalam dependensi:
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 siap diluncurkan: REST API atau tugas pengujian lainnya.  - 5 Anda dapat memeriksanya dengan mengirimkan permintaan GET dari program apa pun yang sesuai ke titik akhir kami. Dalam kasus khusus ini, browser biasa bisa digunakan, tetapi di masa mendatang kita memerlukan Tukang Pos. REST API atau tugas pengujian lainnya.  - 6 Ya, sebenarnya kami belum menerapkan persyaratan bisnis apa pun, namun kami sudah memiliki aplikasi yang dapat dijalankan dan dapat diperluas hingga fungsionalitas yang diperlukan. Lanjutan: REST API dan Validasi Data
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION