JavaRush /Java Blog /Random-ID /Ikhtisar REST. Bagian 3: Membuat Layanan RESTful di Sprin...

Ikhtisar REST. Bagian 3: Membuat Layanan RESTful di Spring Boot

Dipublikasikan di grup Random-ID
Ini adalah bagian terakhir dari penguraian REST. Di bagian sebelumnya: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 1

Membuat Proyek

Di bagian ini, kita akan membuat aplikasi kecil RESTful menggunakan Spring Boot. Aplikasi kita akan mengimplementasikan operasi CRUD (Buat, Baca, Perbarui, Hapus) pada klien dari contoh bagian terakhir analisis. Pertama, mari buat aplikasi Spring Boot baru melalui menu File -> New -> Project... Di jendela yang terbuka, pilih Spring Initializr dan tentukan Project SDK: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 2Klik tombol Next. Di jendela berikutnya, tentukan jenis proyek Maven, tentukan Grup dan Artefak: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 3Klik tombol Berikutnya. Di jendela berikutnya, kita perlu memilih komponen Spring Framework yang diperlukan untuk proyek tersebut. Spring Web sudah cukup bagi kita: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 4Klik tombol Berikutnya. Selanjutnya, tinggal menentukan nama proyek dan lokasinya di sistem file: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 5Klik tombol Selesai. Proyek telah dibuat, sekarang kita dapat melihat strukturnya: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 6IDEA telah menghasilkan untuk kita deskriptor penerapan sistem pembangunan Maven - pom.xml dan kelas aplikasi utama: RestExampleApplication. Ini kode mereka:
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.javarush.lectures</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 mengelola klien. Jadi hal pertama yang perlu kita lakukan adalah membuat entitas pelanggan. Ini akan menjadi kelas POJO. Mari kita buat sebuah paket modeldi dalam sebuah paket com.javarush.lectures.rest_example. modelMari buat kelas di dalam paket Client:
public class Client {

   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 klien. Langkah selanjutnya adalah membuat layanan yang akan mengimplementasikan operasi ini. Di dalam paket com.javarush.lectures.rest_examplekita akan membuat sebuah paket service, di dalamnya kita akan membuat antarmuka ClientService. Berikut adalah kode antarmuka dengan komentar:
public interface ClientService {

   /**
    * Создает нового клиента
    * @param client - клиент для создания
    */
   void create(Client client);

   /**
    * returns список всех имеющихся клиентов
    * @return список клиентов
    */
   List<client> readAll();

   /**
    * returns клиента по его ID
    * @param id - ID клиента
    * @return - an object клиента с заданным ID
    */
   Client read(int id);

   /**
    * Обновляет клиента с заданным ID,
    * в соответствии с переданным клиентом
    * @param client - клиент в соответсвии с которым нужно обновить данные
    * @param id - id клиента которого нужно обновить
    * @return - true если данные были обновлены, иначе false
    */
   boolean update(Client client, int id);

   /**
    * Удаляет клиента с заданным ID
    * @param id - id клиента, которого нужно удалить
    * @return - true если клиент был удален, иначе false
    */
   boolean delete(int id);
}
Selanjutnya kita perlu membuat implementasi antarmuka ini. Sekarang akan bertindak sebagai repositori klien Map<Integer, Client>. Kunci kartu akan menjadi id klien, dan nilainya akan menjadi klien itu sendiri. Hal ini dilakukan agar tidak membebani contoh dengan spesifik bekerja dengan database. Namun, di masa mendatang kami akan dapat menulis implementasi antarmuka lain yang memungkinkan untuk menghubungkan database nyata. Dalam paket tersebut servicekita akan membuat implementasi antarmuka ClientService:
@Service
public class ClientServiceImpl implements ClientService {

   // Хранorще клиентов
   private static final Map<Integer, Client> CLIENT_REPOSITORY_MAP = new HashMap<>();

   // Переменная для генерации ID клиента
   private static final AtomicInteger CLIENT_ID_HOLDER = new AtomicInteger();

   @Override
   public void create(Client client) {
       final int clientId = CLIENT_ID_HOLDER.incrementAndGet();
       client.setId(clientId);
       CLIENT_REPOSITORY_MAP.put(clientId, client);
   }

   @Override
   public List<Client> readAll() {
       return new ArrayList<>(CLIENT_REPOSITORY_MAP.values());
   }

   @Override
   public Client read(int id) {
       return CLIENT_REPOSITORY_MAP.get(id);
   }

   @Override
   public boolean update(Client client, int id) {
       if (CLIENT_REPOSITORY_MAP.containsKey(id)) {
           client.setId(id);
           CLIENT_REPOSITORY_MAP.put(id, client);
           return true;
       }

       return false;
   }

   @Override
   public boolean delete(int id) {
       return CLIENT_REPOSITORY_MAP.remove(id) != null;
   }
}
Anotasi tersebut @Servicememberi tahu Spring bahwa kelas ini adalah sebuah layanan. Ini adalah tipe kelas khusus di mana beberapa logika bisnis aplikasi diimplementasikan. Selanjutnya, berkat anotasi ini, Spring akan memberi kita sebuah instance dari kelas ini di tempat-tempat yang memerlukannya menggunakan Dependency Injection. Sekarang saatnya membuat pengontrol. Kelas khusus tempat kami mengimplementasikan logika untuk memproses permintaan klien untuk titik akhir (URI). Agar lebih jelas, kita akan membuat kelas ini dalam beberapa bagian. Pertama, mari buat kelas itu sendiri dan perkenalkan ketergantungan padanya ClientService:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }
}
Mari kita perjelas anotasinya: @RestController - memberi tahu Spring bahwa kelas ini adalah pengontrol REST. Itu. kelas ini akan mengimplementasikan logika untuk memproses permintaan klien @Autowired - memberi tahu Spring bahwa ketergantungan perlu disuntikkan di tempat ini. Kami meneruskan antarmuka ke konstruktor ClientService. Kami menandai implementasi layanan ini dengan anotasi @Servicesebelumnya, dan sekarang Spring akan dapat meneruskan contoh implementasi ini ke konstruktor pengontrol. Selanjutnya, kita akan mengimplementasikan langkah demi langkah setiap metode pengontrol untuk memproses operasi CRUD. Mari kita mulai dengan operasi Buat. Untuk melakukan ini, mari kita tulis sebuah metode create:
@PostMapping(value = "/clients")
public ResponseEntity<?> create(@RequestBody Client client) {
   clientService.create(client);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Mari kita lihat metode ini: @PostMapping(value = "/clients")- yang kami maksud di sini adalah metode ini memproses permintaan POST ke alamat /clients. Metode ini akan mengembalikan ResponseEntity<?>. ResponseEntity- kelas khusus untuk mengembalikan tanggapan. Dengan menggunakannya, kita nantinya dapat mengembalikan kode status HTTP ke klien. Metode ini mengambil parameter @RequestBody Client client, nilai parameter ini diganti dari badan permintaan. Abstrak berbicara tentang hal ini @RequestBody. Di dalam isi metode, kami memanggil metode buat pada layanan yang dibuat sebelumnya dan meneruskannya ke pengontrol klien yang diterima dalam parameter. Kemudian kita mengembalikan status 201 Dibuat dengan membuat objek baru ResponseEntitydan meneruskan nilai enum yang diperlukan ke objek tersebut HttpStatus. Selanjutnya, kami mengimplementasikan operasi Read: Pertama, kami mengimplementasikan operasi untuk mendapatkan daftar semua klien yang tersedia:
@GetMapping(value = "/clients")
public ResponseEntity<List<Client>> read() {
   final List<Client> clients = clientService.readAll();

   return clients != null &&  !clients.isEmpty()
           ? new ResponseEntity<>(clients, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Mari kita mulai analisisnya: @GetMapping(value = "/clients")- semuanya mirip dengan anotasi @PostMapping, hanya saja sekarang kita memproses permintaan GET. Kali ini kami kembali ResponseEntity<List<Client>>, hanya saja kali ini, selain status HTTP, kami juga akan mengembalikan isi respons, yang akan menjadi daftar klien. Di pengontrol Spring REST, semua objek POJO, serta kumpulan objek POJO yang dikembalikan sebagai badan respons, secara otomatis diserialkan ke JSON kecuali ditentukan lain secara eksplisit. Ini cukup cocok untuk kami. Di dalam metode ini, dengan menggunakan layanan kami, kami mendapatkan daftar semua klien. Selanjutnya, jika daftarnya tidak null atau kosong, kami mengembalikan ResponseEntitydaftar klien dan status HTTP 200 OK menggunakan kelas tersebut. Jika tidak, kita cukup mengembalikan status HTTP 404 Not Found. Selanjutnya, kami akan menerapkan kemampuan untuk menerima klien berdasarkan idnya:
@GetMapping(value = "/clients/{id}")
public ResponseEntity<Client> read(@PathVariable(name = "id") int id) {
   final Client client = clientService.read(id);

   return client != null
           ? new ResponseEntity<>(client, HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Sesuatu yang baru adalah kita sekarang memiliki variabel path. Variabel yang didefinisikan dalam URI. value = "/clients/{id}". Kami menandainya dengan kurung kurawal. Dan dalam parameter metode kami menerimanya sebagai intvariabel menggunakan anotasi @PathVariable(name = "id"). Metode ini akan menerima permintaan uri dalam bentuk /clients/{id}, yang {id}dapat berupa nilai numerik apa pun. Nilai ini selanjutnya diteruskan ke variabel int id—parameter metode. Di dalam tubuh kami menerima objek Clientmenggunakan layanan kami dan menerima id. Dan kemudian, dengan analogi dengan daftar, kita mengembalikan status 200 OK dan objek itu sendiri Client, atau sekadar status 404 Tidak Ditemukan, jika idtidak ada klien dengan ini di sistem. Tetap menerapkan dua operasi - Perbarui dan Hapus. Berikut ini kode untuk metode tersebut:
@PutMapping(value = "/clients/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Client client) {
   final boolean updated = clientService.update(client, id);

   return updated
           ? new ResponseEntity<>(HttpStatus.OK)
           : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}

@DeleteMapping(value = "/clients/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
   final boolean deleted = clientService.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 penjelasan rincinya. Satu-satunya hal yang perlu disebutkan adalah bahwa metode ini updatememproses permintaan PUT (annotation @PutMapping), dan metode tersebut deletememproses permintaan DELETE (annotation DeleteMapping). Berikut kode pengontrol lengkapnya:
@RestController
public class ClientController {

   private final ClientService clientService;

   @Autowired
   public ClientController(ClientService clientService) {
       this.clientService = clientService;
   }

   @PostMapping(value = "/clients")
   public ResponseEntity<?> create(@RequestBody Client client) {
       clientService.create(client);
       return new ResponseEntity<>(HttpStatus.CREATED);
   }

   @GetMapping(value = "/clients")
   public ResponseEntity<List<Client>> read() {
       final List<client> clients = clientService.readAll();

       return clients != null &&  !clients.isEmpty()
               ? new ResponseEntity<>(clients, HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_FOUND);
   }

   @GetMapping(value = "/clients/{id}")
   public ResponseEntity<Client> read(@PathVariable(name = "id") int id) {
       final Client client = clientService.read(id);

       return client != null
               ? new ResponseEntity<>(client, HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_FOUND);
   }

   @PutMapping(value = "/clients/{id}")
   public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Client client) {
       final boolean updated = clientService.update(client, id);

       return updated
               ? new ResponseEntity<>(HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
   }

   @DeleteMapping(value = "/clients/{id}")
   public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
       final boolean deleted = clientService.delete(id);

       return deleted
               ? new ResponseEntity<>(HttpStatus.OK)
               : new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
   }
}
Hasilnya, struktur proyek kami terlihat seperti ini: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 7

Peluncuran dan pengujian

Untuk menjalankan aplikasi kita, jalankan saja metode yang mainada di kelas RestExampleApplication. Dan untuk menguji layanan web RESTful, Anda perlu mengunduh perangkat lunak baru) Faktanya adalah permintaan GET cukup mudah dikirim dari browser biasa, tetapi untuk POST, PUT dan DELETE browser biasa saja tidak cukup. Jangan khawatir: Anda dapat menggunakan Tukang Pos untuk mengirim permintaan HTTP apa pun. Anda dapat mengunduhnya dari sini . Setelah mengunduh dan menginstal, kami mulai menguji aplikasi kami. Untuk melakukan ini, buka program dan buat permintaan baru: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 9Klik tombol Baru di sudut kiri atas. Selanjutnya, pilih Permintaan: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 10Selanjutnya, beri nama dan simpan. Sekarang mari kita coba mengirim permintaan POST ke server dan membuat klien pertama: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 11Kita membuat beberapa klien dengan cara ini. Kemudian kita ubah jenis permintaan menjadi GET dan mengirimkannya ke server: Ikhtisar REST.  Bagian 3: Membuat Layanan RESTful di Spring Boot - 12

Hasil umum

Selamat: kita telah membahas cukup banyak topik REST. Semua materinya ternyata banyak sekali, namun semoga bermanfaat bagi Anda:
  1. Kami mempelajari apa itu REST.

  2. Kami berkenalan dengan sejarah REST.

  3. Kami berbicara tentang batasan dan prinsip gaya arsitektur ini:

    • membawa arsitektur ke model client-server;
    • kurangnya kondisi;
    • cache;
    • keseragaman antarmuka;
    • lapisan;
    • kode sesuai permintaan (pembatasan opsional).
  4. Kami memeriksa keuntungan yang diberikan REST

  5. Kami memeriksa secara rinci bagaimana server dan klien berinteraksi satu sama lain menggunakan protokol HTTP.

  6. Mari kita lihat lebih dekat permintaan dan tanggapannya. Komponennya dibongkar.

  7. Akhirnya, kami melanjutkan latihan dan menulis aplikasi RESTful kecil kami sendiri di Spring Boot. Dan kami bahkan belajar cara mengujinya menggunakan program Postman.

Fiuh. Ternyata banyak sekali, tapi tetap saja ada yang harus dilakukan sebagai pekerjaan rumah.

Pekerjaan rumah

Coba yang berikut ini:
  1. Mengikuti uraian di atas, buat proyek Spring Boot Anda sendiri dan terapkan logika yang sama seperti dalam kuliah. Ulangi semuanya 1 dalam 1.
  2. Luncurkan. aplikasi.
  3. Unduh dan atur Tukang Pos (atau alat lain untuk mengirim permintaan, bahkan curl).
  4. Uji permintaan POST dan GET dengan cara yang sama seperti yang dijelaskan dalam kuliah.
  5. Uji sendiri permintaan PUT dan DELETE.
Bagian 1: Apa itu REST Bagian 2: Komunikasi antara klien dan server
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION