JavaRush /Blog Jawa /Random-JV /REST API lan tugas test liyane.
Денис
tingkat
Киев

REST API lan tugas test liyane.

Diterbitake ing grup
Bagian I: Diwiwiti Where to start? Cukup aneh, nanging saka spesifikasi teknis. Penting banget kanggo mesthekake yen sawise maca TOR sing dikirim, sampeyan ngerti kanthi lengkap apa sing ditulis ing kono lan apa sing dikarepake klien. Kaping pisanan, iki penting kanggo implementasine luwih lanjut, lan kaping pindho, yen sampeyan ora nindakake apa sing dikarepake, ora bakal migunani kanggo sampeyan. Supaya ora mbuang hawa, ayo gawe sketsa spesifikasi teknis sing prasaja. Dadi, aku pengin layanan sing bisa ngirim data, bakal disimpen ing layanan kasebut lan bali menyang aku. Aku uga kudu bisa nganyari lan mbusak data iki yen perlu . Saperangan ukara kayane ora jelas, ta? Kepiye carane ngirim data ing kana? Apa teknologi sing digunakake? Apa format data iki? Uga ora ana conto data mlebu lan metu. Kesimpulan - spesifikasi teknis wis ala . Coba rephrase: Kita butuh layanan sing bisa ngolah panjalukan HTTP lan nggarap data sing ditransfer. Iki bakal dadi database rekaman personel. Kita bakal duwe karyawan, dibagi dening departemen lan spesialisasi, karyawan bisa uga duwe tugas sing ditugasake. Tugas kita yaiku ngotomatisasi proses akuntansi kanggo karyawan sing disewa, dipecat, ditransfer, uga proses nemtokake lan mbatalake tugas nggunakake API REST. Minangka Fase 1, kita saiki mung nggarap karyawan. Layanan kasebut kudu duwe sawetara titik pungkasan kanggo nggarap: - POST / karyawan - request POST, sing kudu nampa obyek JSON kanthi data babagan karyawan. Objek iki kudu disimpen ing basis data; yen obyek kasebut wis ana ing basis data, informasi ing kolom kasebut kudu dianyari karo data anyar. - GET / karyawan - Njaluk GET sing ngasilake kabeh dhaptar karyawan sing disimpen ing database - DELETE - DELETE / karyawan kanggo mbusak model data karyawan tartamtu:
{
  "firstName": String,
  "lastName": String,
  "department": String,
  "salary": String
  "hired": String //"yyyy-mm-dd"
  "tasks": [
  	//List of tasks, not needed for Phase 1
  ]
}
Bagean II: Piranti kanggo pakaryan Dadi, ruang lingkup kerja luwih jelas, nanging kepiye carane? Temenan, tugas kuwi ing test diwenehi karo saperangan saka gol aplikasi, kanggo ndeleng carane kode, kanggo meksa sampeyan nggunakake Spring lan bisa sethitik karo database. Nah, ayo iki. Kita butuh proyek SpringBoot kanthi dhukungan REST API lan database. Ing situs web https://start.spring.io/ sampeyan bisa nemokake kabeh sing dibutuhake. REST API utawa tugas test liyane.  - 1 Sampeyan bisa milih sistem mbangun, basa, versi SpringBoot, nyetel setelan artefak, versi Java, lan dependensi. Ngeklik tombol Tambah Dependensi bakal mbukak menu karakteristik kanthi garis telusuran. Calon pisanan kanggo tembung liyane lan data yaiku Spring Web lan Spring Data - kita bakal nambah. Lombok minangka perpustakaan trep sing ngidini sampeyan nggunakake anotasi kanggo nyingkirake kode kilometer kanthi metode getter lan setter. Kanthi ngeklik tombol Generate, kita bakal nampa arsip karo proyek sing wis bisa dibongkar lan dibukak ing IDE favorit. Kanthi gawan, kita bakal nampa project kosong, karo file konfigurasi kanggo sistem mbangun (ing cilik iku bakal gradle, nanging karo Maven iku ora ana prabédan dhasar, lan siji file wiwitan spring) Wong enten bisa mbayar manungsa waé kanggo rong bab REST API utawa tugas test liyane.  - 2 . . Kaping pisanan, aku duwe rong setelan file application.properties lan application.yml. Kanthi gawan, sampeyan bakal entuk persis properti - file kosong ing ngendi sampeyan bisa nyimpen setelan, nanging kanggo kula format yml katon luwih gampang diwaca, saiki aku bakal nuduhake perbandingan: Senadyan kasunyatan manawa gambar REST API utawa tugas test liyane.  - 3 ing sisih kiwa katon luwih kompak. , iku gampang kanggo ndeleng jumlah gedhe saka duplikasi ing path sifat. Gambar ing sisih tengen minangka file yml biasa kanthi struktur wit sing cukup gampang diwaca. Aku bakal nggunakake file iki mengko ing project. Babagan kapindho sing bisa dingerteni wong sing ati-ati yaiku proyekku wis duwe sawetara paket. Ora ana kode sing waras, nanging kudu ditindakake. Kepiye carane nulis aplikasi? Duwe tugas tartamtu, kita kudu ngrusak - dipecah dadi subtugas cilik lan miwiti implementasine sing konsisten. Apa sing dibutuhake saka kita? Kita kudu nyedhiyakake API sing bisa digunakake klien; isi paket pengontrol bakal tanggung jawab kanggo bagean fungsi kasebut. Bagian kapindho aplikasi yaiku database - paket kegigihan. Ing kono kita bakal nyimpen barang kayata Entitas Database (Entitas) uga Repositori - antarmuka musim semi khusus sing ngidini sampeyan sesambungan karo database. Paket layanan bakal ngemot kelas layanan. Kita bakal ngomong babagan apa Layanan jinis Spring ing ngisor iki. Lan pungkasan, nanging paling ora, paket utils. Kelas utilitarian kanthi macem-macem cara tambahan bakal disimpen ing kana, contone, kelas kanggo nggarap tanggal lan wektu, utawa kelas kanggo nggarap senar, lan sapa sing ngerti. Ayo dadi miwiti ngleksanakake bagean pisanan saka fungsi. Bab III: Pengawas
@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());
    }
}
Saiki kelas EmployeeController kita katon kaya iki. Ana sawetara perkara penting sing kudu digatekake ing kene. 1. Anotasi ing ndhuwur kelas, @RestController pisanan ngandhani aplikasi kita yen kelas iki bakal dadi titik pungkasan. 2. @RequestMapping, sanajan ora wajib, minangka anotasi sing migunani, ngidini sampeyan nyetel path tartamtu kanggo titik pungkasan. Sing. supaya bisa ngalahake, sampeyan kudu ngirim panjalukan ora menyang localhost: port / karyawan, nanging ing kasus iki menyang localhost: 8086 / api / v1 / karyawan Sejatine, saka ngendi asale api / v1 lan karyawan kasebut? Saka application.yml kita Yen sampeyan ndeleng kanthi teliti, sampeyan bisa nemokake baris ing ngisor iki:
application:
  endpoint:
    root: api/v1
    employee: employee
    task: task
Kaya sing sampeyan ngerteni, kita duwe variabel kayata application.endpoint.root lan application.endpoint.employee, iki persis sing daktulis ing anotasi, aku nyaranake ngelingi cara iki - bakal ngirit akeh wektu kanggo ngembangake utawa nulis ulang fungsi - iku tansah luwih trep kanggo duwe kabeh ing config, lan ora hardcode kabeh project. 3. @RequiredArgsConstructor minangka anotasi Lombok, perpustakaan sing trep sing ngidini sampeyan ora nulis perkara sing ora perlu. Ing kasus iki, anotasi padha karo kasunyatan sing kelas bakal duwe konstruktor umum karo kabeh kolom ditandhani minangka final.
public EmployeeController(EmployeeService employeeService) {
    this.employeeService=employeeService;
}
Nanging kenapa kita kudu nulis kaya ngono yen siji anotasi cukup? :) Miturut cara, Sugeng, lapangan final paling pribadi iki ora luwih saka Injeksi Dependensi kondhang. Ayo nerusake, sejatine, lapangan apa sing diarani EmployeeService? Iki bakal dadi salah sawijining layanan ing proyek kita sing bakal ngolah panjaluk kanggo titik pungkasan iki. Ide ing kene gampang banget. Saben kelas kudu duwe tugas dhewe lan ora kudu kakehan karo tumindak sing ora perlu. Yen iki controller, supaya njupuk care saka nampa panjalukan lan ngirim respon, nanging kita luwih ngandelake Processing kanggo layanan tambahan. Wangsulan: Bab ingkang pungkasan sing ditinggalake ing kelas iki yaiku siji-sijine cara sing ngasilake dhaptar kabeh karyawan perusahaan sing nggunakake layanan kasebut ing ndhuwur. Dhaptar kasebut dhewe dibungkus ing entitas sing diarani ResponseEntity. Aku nindakake iki supaya ing mangsa ngarep, yen perlu, aku bisa gampang bali kode respon lan pesen aku kudu, kang sistem otomatis bisa ngerti. Dadi, contone, ResponseEntity.ok () bakal ngasilake kode 200th, sing bakal ngomong yen kabeh apik, nanging yen aku bali, contone.
return ResponseEntity.badRequest().body(Collections.emptyList());
banjur klien bakal nampa kode 400 - ala reuqest lan dhaftar kosong ing respon. Biasane kode iki bali yen panjalukan ora bener. Nanging siji controller ora cukup kanggo kita miwiti aplikasi. Ketergantungan kita ora bakal ngidini kita nindakake iki, amarga kita isih kudu duwe basis :) Nah, ayo pindhah menyang bagean sabanjure. Part IV: ketekunan prasaja Wiwit tugas utama kita kanggo miwiti aplikasi, kita bakal matesi dhéwé kanggo saperangan stubs kanggo saiki. Sampeyan wis katon ing kelas Controller sing kita bali dhaftar obyek saka jinis Employee, iki bakal kita entitas kanggo database. Ayo digawe ing paket demo.persistence.entity .. Ing mangsa ngarep, paket entitas bisa ditambah karo entitas liyane saka database.
@Entity
@Data
@Accessors(chain = true)
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
}
Iki kelas sing prasaja minangka lawang, Anotasi sing ngandika persis ing ngisor iki: iki entitas database @Entity, iki kelas karo data @Data - Lombok. Lombok mbiyantu bakal nggawe kanggo kita kabeh getter perlu, setter, konstruktor - stuffing lengkap. Ya, ceri cilik ing kue yaiku @Accessors(chain = true) Nyatane, iki minangka implementasine saka pola Builder. Upaminipun sampeyan duwe kelas karo Bunch saka kothak sing arep kanggo nemtokake ora liwat konstruktor, nanging dening cara. Ing urutan beda, mbok menawa ora kabeh bebarengan. Sampeyan ora ngerti apa jenis logika ing aplikasi sampeyan. Anotasi iki minangka kunci kanggo tugas iki. Ayo katon:
public Employee createEmployee() {
    return new Employee().setName("Peter")
        				.setAge("28")
        				.setDepartment("IT");
}
Coba anggep kabeh lapangan iki ana ing kelas kita😄Sampeyan bisa nemtokake, ora bisa nemtokake, bisa nyampur ing panggonan. Ing kasus mung 3 properti, iki ora katon kaya sing luar biasa. Nanging ana kelas kanthi jumlah properti sing luwih akeh, contone 50. Lan nulis kaya
public Employee createEmployee() {
    return new Employee("Peter", "28", "IT", "single", "loyal", List.of(new Task("do Something 1"), new Task ("do Something 2")));
}
Ora katon ayu banget, ta? Kita uga kudu strictly tindakake urutan nambah variabel ing sesuai karo konstruktor. Nanging, aku nyimpang, ayo bali menyang titik kasebut. Saiki kita duwe siji lapangan (wajib) - pengenal unik. Ing kasus iki, iki minangka nomer jinis Long, sing digawe kanthi otomatis nalika disimpen ing database. Mulane, anotasi @Id kanthi jelas nuduhake yen iki minangka pengenal unik; @GeneratedValue tanggung jawab kanggo generasi unik. Perlu dicathet yen @Id bisa ditambahake menyang kolom sing ora digawe kanthi otomatis, nanging masalah keunikan kudu ditangani kanthi manual. Apa sing bisa dadi pengenal karyawan sing unik? Inggih, contone, jeneng lengkap + departemen ... Nanging, wong duwe jeneng lengkap, lan ana kasempatan sing padha bakal bisa ing departemen padha, cilik, nanging ana - tegese kaputusan iku ala. Iku bakal bisa kanggo nambah Bunch saka lapangan liyane, kayata tanggal ngrekrut, kutha, nanging kabeh iki, misale jek kula, complicates logika banget. Sampeyan bisa uga kepingin weruh, kepiye carane akeh lapangan bisa dadi unik sekaligus? Aku mangsuli - mbok menawa. Yen sampeyan kepengin weruh, sampeyan bisa google babagan kaya @Embeddable lan @Embedded Inggih, kita wis rampung karo inti. Saiki kita butuh repositori sing prasaja. Bakal katon kaya iki:
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}
Ya mung kuwi. Mung antarmuka, kita disebut EmployeeRepository, iku ngluwihi JpaRepository kang wis loro paramèter diketik, pisanan tanggung jawab kanggo jinis data dianggo karo, kaloro kanggo jinis tombol. Ing kasus kita, iki minangka Karyawan lan Long. Cukup kanggo saiki. Sentuhan pungkasan sadurunge ngluncurake aplikasi yaiku layanan kita:
@Service
@RequiredArgsConstructor
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    public List<Employee> getAllEmployees() {
        return List.of(new Employee().setId(123L));
    }
}
Ana RequiredArgsConstructor sing wis dikenal lan anotasi @Service anyar - iki sing biasane nuduhake lapisan logika bisnis. Nalika mbukak konteks musim semi, kelas sing ditandhani karo anotasi iki bakal digawe minangka Beans. Nalika ing kelas EmployeeController kita wis digawe EmployeeService property final lan ditempelake RequiredArgsConstructor (utawa digawe konstruktor dening tangan) Spring, nalika initializing aplikasi, bakal nemokake panggonan iki lan slip kita obyek kelas menyang variabel iki. Standar ing kene yaiku Singleton - i.e. bakal ana siji obyek kanggo kabeh pranala kasebut; iki penting kanggo dipikirake nalika ngrancang aplikasi kasebut. Bener, mung iku, aplikasi kasebut bisa diluncurake. Aja lali ngetik setelan sing dibutuhake ing konfigurasi. REST API utawa tugas test liyane.  - 4 Aku ora bakal njlèntrèhaké carane nginstal database, nggawe pangguna lan database dhewe, nanging aku mung bakal nyathet yen ing URL aku nggunakake rong paramèter tambahan - useUnicore = true lan characterEncoding = UTF-8. Iki ditindakake supaya teks bakal ditampilake luwih utawa kurang padha ing sistem apa wae. Nanging, yen sampeyan kesed kanggo tinker karo database lan pancene pengin poke sak kode digunakake, ana solusi cepet: 1. Tambah dependensi ing ngisor iki kanggo build.gradle:
implementation 'com.h2database:h2:2.1.214'
2. Ing application.yml sampeyan kudu nyunting sawetara properti, aku bakal menehi conto lengkap bagean spring kanggo gamblang:
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 bakal disimpen ing folder proyek, ing file sing disebut mydb . Nanging aku nyaranake nginstal database lengkap 😉 Artikel sing migunani babagan topik: Boot Spring Kanthi Database H2 Yen ngono, aku bakal menehi versi lengkap build.gradle kanggo ngilangi bedane ing 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 siyap diluncurake: REST API utawa tugas test liyane.  - 5 Sampeyan bisa mriksa kanthi ngirim panjaluk GET saka program sing cocog menyang titik pungkasan. Ing kasus tartamtu iki, browser biasa bakal ditindakake, nanging ing mangsa ngarep kita butuh Tukang Pos. REST API utawa tugas test liyane.  - 6 Ya, nyatane, kita durung ngetrapake syarat bisnis, nanging kita wis duwe aplikasi sing diwiwiti lan bisa ditambahake menyang fungsi sing dibutuhake. Terus: REST API lan Validasi Data
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION