Ini adalah bagian terakhir dari ikhtisar kami tentang REST. Di bagian sebelumnya, kami membahas:
Membuat proyek
Pada bagian ini, kita akan membuat aplikasi RESTful kecil menggunakan Spring Boot. Aplikasi kita akan menerapkan operasi CRUD (Buat, Baca, Perbarui, Hapus) pada pelanggan dari contoh di bagian ikhtisar sebelumnya . Untuk memulai, kita akan membuat aplikasi Spring Boot baru melalui menu: File -> New -> Project... Di jendela yang terbuka, pilih Spring Initializr dan tentukan Project SDK: Klik tombol "Next". Di jendela berikutnya, tentukan "Proyek Maven" sebagai jenis proyek, tentukan "Grup" dan "Artefak": Klik tombol "Berikutnya". Di jendela berikutnya, kita perlu memilih komponen Spring Framework yang diperlukan untuk proyek tersebut. Spring Web akan cukup bagi kami: Klik tombol "Berikutnya". Sekarang yang tersisa hanyalah menunjukkan nama proyek dan lokasinya di sistem file: Klik tombol "Selesai". Proyek telah dibuat, dan sekarang kita dapat melihat strukturnya: IDEA menghasilkan deskriptor penyebaran Maven (pom.xml) dan kelas utama aplikasi (RestExampleApplication
) untuk kita. Inilah yang mereka terlihat seperti:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.codegym.lessons/groupId>
<artifactId>rest_example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rest_example</name>
<description>REST example project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Aplikasi Contoh Istirahat:
@SpringBootApplication
public class RestExampleApplication {
public static void main(String[] args) {
SpringApplication.run(RestExampleApplication.class, args);
}
}
Membuat fungsionalitas REST
Aplikasi kami adalah sistem manajemen pelanggan. Jadi, hal pertama yang perlu kita lakukan adalah membuat entitas pelanggan. Ini akan menjadi kelas POJO (objek Java lama biasa). Buatmodel
paket di dalam com.codegym.lessons.rest_example
paket. Di dalam model
paket, buat Customer
:
public class Customer {
private Integer id;
private String name;
private String email;
private String phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
Layanan ini akan mengimplementasikan operasi CRUD pada pelanggan. Langkah selanjutnya adalah membuat layanan yang akan mengimplementasikan operasi ini. Di dalam com.codegym.lessons.rest_example
package, buat sebuah service
package. Dan di dalamnya, buat CustomerService
antarmuka. Berikut adalah kode antarmuka dengan komentar:
public interface CustomerService {
/**
* Creates a new customer
* @param customer - Customer to be created
*/
void create(Customer customer);
/**
* Returns a list of all existing customers
* @return List of customers
*/
List<Customer> readAll();
/**
* Returns a customer based on its ID
* @param id - Customer ID
* @return - Customer object with the given ID
*/
Customer read(int id);
/**
* Updates the customer with the given ID,
* according to the passed customer
* @param customer - Customer to use to update the data
* @param id - ID of the customer you want to update
* @return - true if the data has been updated, otherwise false
*/
boolean update(Customer customer, int id);
/**
* Deletes the customer with the given ID
* @param id - ID of the customer to be deleted
* @return - true if the customer was deleted, otherwise false
*/
boolean delete(int id);
}
Selanjutnya, kita perlu mengimplementasikan antarmuka ini. Sekarang Map<Integer, Customer>
akan menyimpan pelanggan kami. Kunci peta akan menjadi ID pelanggan, dan nilainya akan menjadi pelanggan itu sendiri. Ini dilakukan agar tidak membebani contoh ini dengan spesifikasi bekerja dengan database nyata. Namun, di masa mendatang kami akan dapat menulis implementasi lain dari antarmuka, yang memungkinkan untuk terhubung ke database nyata. Dalam service
paket, buat implementasi antarmuka CustomerService
:
@Service
public class CustomerServiceImpl implements CustomerService {
// Customer repository
private static final Map<Integer, Customer> CUSTOMER_REPOSITORY_MAP = new HashMap<>();
// Variable for generating a customer ID
private static final AtomicInteger CUSTOMER_ID_HOLDER = new AtomicInteger();
@Override
public void create(Customer customer) {
final int customerId = CUSTOMER_ID_HOLDER.incrementAndGet();
customer.setId(customerId);
CUSTOMER_REPOSITORY_MAP.put(customerId, customer);
}
@Override
public List<Customer> readAll() {
return new ArrayList<>(CUSTOMER_REPOSITORY_MAP.values());
}
@Override
public Customer read(int id) {
return CUSTOMER_REPOSITORY_MAP.get(id);
}
@Override
public boolean update(Customer customer, int id) {
if (CUSTOMER_REPOSITORY_MAP.containsKey(id)) {
customer.setId(id);
CUSTOMER_REPOSITORY_MAP.put(id, customer);
return true;
}
return false;
}
@Override
public boolean delete(int id) {
return CUSTOMER_REPOSITORY_MAP.remove(id) != null;
}
}
Anotasi @Service
memberi tahu pegas bahwa kelas ini adalah layanan. Ini adalah jenis kelas khusus yang mengimplementasikan beberapa logika aplikasi bisnis. Selanjutnya, berkat anotasi ini, Spring akan menggunakan injeksi ketergantungan untuk memberi kita instance kelas ini di semua tempat yang membutuhkannya. Sekarang saatnya membuat controller. Ini adalah kelas khusus tempat kami akan mengimplementasikan logika untuk memproses permintaan klien yang dikirim ke titik akhir (URI). Untuk membuat semua ini lebih jelas, kita akan membuat kelas ini secara bertahap. Pertama, buat kelas itu sendiri dan tambahkan dependensi pada CustomerService
:
@RestController
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
}
Mari kita jelaskan anotasinya: @RestController memberi tahu Spring bahwa kelas ini adalah pengontrol REST. Dengan kata lain, kelas ini mengimplementasikan logika untuk memproses permintaan klien. @Autowired memberi tahu Spring bahwa ketergantungan perlu ditambahkan di sini. Kami meneruskan CustomerService
antarmuka ke konstruktor. Sebelumnya, kami menandai implementasi layanan ini dengan anotasi @Service
, dan sekarang Spring akan dapat meneruskan instance implementasi ini ke konstruktor controller. Selanjutnya, kami akan menerapkan setiap metode pengontrol untuk menangani operasi CRUD. Mari kita mulai dengan operasi pembuatan. Untuk melakukan ini, kami menulis create
metode:
@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
customerService.create(customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
Mari kita analisis metode ini: @PostMapping(value = "/customers")
artinya metode ini memproses permintaan POST yang dikirim ke alamat "/pelanggan". Metode mengembalikan a ResponseEntity<?>
. A ResponseEntity
adalah kelas khusus untuk mengembalikan tanggapan. Nanti, kami akan menggunakannya untuk mengembalikan kode status HTTP ke klien. Metode ini memiliki @RequestBody Customer customer
parameter. Nilai parameter ini berasal dari badan permintaan. Anotasi @RequestBody
menunjukkan ini. Di dalam tubuh metode, kami memanggil create()
metode pada layanan yang dibuat sebelumnya dan meneruskannya ke pengontrol pelanggan yang diterima di parameter. Kemudian kami mengembalikan status "201 Dibuat" dengan membuat ResponseEntity
objek baru dan meneruskan HttpStatus
bidang enum yang sesuai ke sana. Selanjutnya, kita akan mengimplementasikanread
operasi: Pertama, kami akan menerapkan operasi untuk mendapatkan daftar semua pelanggan yang tersedia:
@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
final List<Customer> customers = customerService.readAll();
return customers != null && !customers.isEmpty()
? new ResponseEntity<>(customers, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Mari selami: @GetMapping(value = "/customers")
— semua yang ada di sini mirip dengan @PostMapping
anotasi, tetapi sekarang kami sedang memproses permintaan GET. Kali ini kami mengembalikan a ResponseEntity<List<Customer>>
, dan selain status HTTP, kami juga akan mengembalikan badan tanggapan, yang akan menjadi daftar pelanggan. Di pengontrol REST Spring, semuanya adalah objek POJO dan kumpulan objek POJO, yang dikembalikan sebagai badan respons dan secara otomatis diserialisasikan ke dalam JSON, kecuali ditentukan lain. Ini sangat cocok untuk kita. Di dalam metode tersebut, kami menggunakan layanan kami untuk mendapatkan daftar semua pelanggan. Selanjutnya, jika daftar tidak null dan tidak kosong, maka kita menggunakan theResponseEntity
kelas untuk mengembalikan daftar pelanggan dan kode status HTTP "200 OK". Jika tidak, kami cukup mengembalikan kode status HTTP "404 Not Found". Sekarang kami akan menerapkan kemampuan untuk mendapatkan pelanggan menggunakan ID-nya:
@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
final Customer customer = customerService.read(id);
return customer != null
? new ResponseEntity<>(customer, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Satu hal baru di sini adalah variabel path. Variabel didefinisikan dalam URI: value = "/customers/{id}"
. Kami menunjukkannya dalam kurung kurawal. Dan kami menerimanya sebagai int
parameter metode menggunakan @PathVariable(name = "id")
anotasi. Metode ini akan menerima permintaan yang dikirim ke URI dalam bentuk /customers/{id}
, yang {id}
mewakili nilai numerik apa pun. Nilai ini selanjutnya diteruskan melalui int id
variabel ke parameter metode. Di dalam tubuh, kita mendapatkan Customer
objek menggunakan layanan kita dan menerima id
. Dan kemudian, dengan analogi dengan daftar, kami mengembalikan status "200 OK" dan Customer
objek itu sendiri, atau hanya status "404 Tidak Ditemukan" jika sistem tidak memiliki pelanggan dengan itu id
. Kami masih perlu menerapkan dua operasi: perbarui dan hapus. Berikut adalah kode untuk metode ini:
@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
final boolean updated = customerService.update(customer, id);
return updated
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
final boolean deleted = customerService.delete(id);
return deleted
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
Pada dasarnya tidak ada yang baru dalam metode ini, jadi kami akan melewatkan deskripsi mendetail. Satu-satunya hal yang perlu disebutkan adalah bahwa update()
metode tersebut menangani permintaan PUT ( @PutMapping
anotasi), dan delete()
metode tersebut menangani permintaan DELETE ( DeleteMapping
anotasi). Berikut adalah kode lengkap untuk controller:
@RestController
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
customerService.create(customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
final List<Customer> customers = customerService.readAll();
return customers != null && !customers.isEmpty()
? new ResponseEntity<>(customers, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
final Customer customer = customerService.read(id);
return customer != null
? new ResponseEntity<>(customer, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
final boolean updated = customerService.update(customer, id);
return updated
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
final boolean deleted = customerService.delete(id);
return deleted
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
}
Akibatnya, struktur proyek kami adalah sebagai berikut:
Peluncuran dan pengujian
Untuk memulai aplikasi kita, jalankan sajamain()
metode di RestExampleApplication
kelas. Tetapi untuk menguji layanan web RESTful, kami perlu mengunduh perangkat lunak tambahan. Faktanya adalah permintaan GET cukup mudah dikirim dari browser biasa, tetapi browser biasa tidak dapat mengirim permintaan POST, PUT, dan DELETE. Jangan khawatir: Anda dapat menggunakan program bernama Postman untuk mengirimkan permintaan HTTP apa pun. Anda dapat mengunduhnya di sini . Setelah mengunduh dan menginstal Postman, kami mulai menguji aplikasi kami. Untuk melakukannya, buka program dan buat permintaan baru: Klik tombol "Baru" di pojok kiri atas. Selanjutnya, pilih "Permintaan": Selanjutnya, beri nama dan simpan. Sekarang mari kita coba mengirim permintaan POST ke server dan membuat pelanggan pertama: Kami membuat beberapa pelanggan dengan cara ini. Kemudian kami mengubah jenis permintaan menjadi GET dan mengirim permintaan ke server:
Ringkasan
Selamat! Kami sudah cukup membahas REST. Materinya banyak sekali, tapi semoga bermanfaat bagi Anda:-
Kami belajar apa itu REST.
-
Kami belajar tentang bagaimana REST muncul.
-
Kami berbicara tentang batasan dan prinsip di balik gaya arsitektur ini:
- arsitektur klien-server
- tanpa kewarganegaraan
- caching
- antarmuka yang seragam
- lapisan
- kode sesuai permintaan (opsional)
-
Kami menjelajahi manfaat yang diberikan oleh REST
-
Kami memeriksa secara detail bagaimana server dan klien berinteraksi satu sama lain melalui protokol HTTP.
-
Kami melihat lebih dekat pada permintaan dan tanggapan. Kami membedah bagian penyusunnya.
-
Akhirnya, kami mendapat pengalaman praktis dengan menulis aplikasi RESTful kecil kami sendiri menggunakan Spring Boot. Dan kami bahkan belajar cara mengujinya menggunakan Postman.
Pekerjaan rumah
Coba yang berikut ini:- Mengikuti uraian di atas, buat proyek Spring Boot Anda sendiri dan implementasikan logika yang sama seperti di pelajaran. Ulangi semuanya dengan tepat.
- Luncurkan aplikasi.
- Unduh dan konfigurasikan Postman (atau alat lain untuk mengirim permintaan, misalnya curl).
- Uji permintaan POST dan GET dengan cara yang sama seperti yang dijelaskan dalam pelajaran.
- Uji permintaan PUT dan DELETE sendiri.
GO TO FULL VERSION