CodeGym /Blog Java /Ngẫu nhiên /Tổng quan về REST. Phần 3: Xây dựng dịch vụ RESTful trên ...
John Squirrels
Mức độ
San Francisco

Tổng quan về REST. Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot

Xuất bản trong nhóm
Đây là phần cuối cùng trong tổng quan về REST của chúng ta. Trong các phần trước, chúng tôi đã đề cập: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 1

Tạo một dự án

Trong phần này, chúng ta sẽ tạo một ứng dụng RESTful nhỏ bằng Spring Boot. Ứng dụng của chúng tôi sẽ triển khai các thao tác CRUD (Tạo, Đọc, Cập nhật, Xóa) trên các khách hàng từ ví dụ trong phần trước của tổng quan. Để bắt đầu, chúng ta sẽ tạo một ứng dụng Spring Boot mới thông qua menu: Tệp -> Mới -> Dự án... Trong cửa sổ mở ra, chọn Spring Initializr và chỉ định SDK dự án: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 2Nhấp vào nút "Tiếp theo". Trong cửa sổ tiếp theo, chỉ định "Maven Project" làm loại dự án, chỉ định "Group" và "Artifact": Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 3Nhấp vào nút "Next". Trong cửa sổ tiếp theo, chúng ta cần chọn các thành phần Spring Framework cần thiết cho dự án. Spring Web sẽ đủ cho chúng ta: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 4Nhấp vào nút "Tiếp theo". Bây giờ tất cả những gì còn lại là chỉ ra tên của dự án và vị trí của nó trong hệ thống tệp: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 5Nhấp vào nút "Hoàn tất". Dự án đã được tạo và bây giờ chúng ta có thể thấy cấu trúc của nó: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 6IDEA đã tạo bộ mô tả triển khai Maven (pom.xml) và lớp chính của ứng dụng ( RestExampleApplication) cho chúng ta. Đây là những gì họ trông giống như:

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>
Ứng dụng RestExample:

@SpringBootApplication
public class RestExampleApplication {

   public static void main(String[] args) {
       SpringApplication.run(RestExampleApplication.class, args);
   }

}

Tạo chức năng REST

Ứng dụng của chúng tôi là một hệ thống quản lý khách hàng. Vì vậy, điều đầu tiên chúng ta cần làm là tạo một thực thể khách hàng. Nó sẽ là một lớp POJO (đối tượng Java cũ đơn giản). Tạo một modelgói bên trong com.codegym.lessons.rest_examplegói. Bên trong modelgói, tạo 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;
   }
}
Dịch vụ sẽ thực hiện các hoạt động CRUD trên khách hàng. Bước tiếp theo là tạo một dịch vụ sẽ thực hiện các thao tác này. Trong com.codegym.lessons.rest_examplegói, tạo một servicegói. Và bên trong đó, tạo một CustomerServicegiao diện. Đây là mã giao diện với các bình luận:

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);
}
Tiếp theo, chúng ta cần triển khai giao diện này. Bây giờ a Map<Integer, Customer>sẽ lưu trữ khách hàng của chúng tôi. Khóa của bản đồ sẽ là ID khách hàng và giá trị sẽ là chính khách hàng. Điều này được thực hiện để không làm quá tải ví dụ này với các chi tiết cụ thể khi làm việc với cơ sở dữ liệu thực. Tuy nhiên, trong tương lai, chúng tôi sẽ có thể viết một triển khai giao diện khác, giúp kết nối với cơ sở dữ liệu thực. Trong servicegói, hãy tạo một triển khai giao CustomerServicediện:

@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;
   }
}
Chú @Servicethích cho mùa xuân biết rằng lớp này là một dịch vụ. Đây là một loại lớp đặc biệt thực hiện một số logic ứng dụng nghiệp vụ. Sau đó, nhờ chú thích này, Spring sẽ sử dụng phép nội xạ phụ thuộc để cung cấp cho chúng ta một thể hiện của lớp này ở tất cả những nơi cần thiết. Bây giờ là lúc để tạo một bộ điều khiển. Đây là một lớp đặc biệt, nơi chúng tôi sẽ triển khai logic để xử lý các yêu cầu của máy khách được gửi đến các điểm cuối (URI). Để làm cho tất cả điều này rõ ràng hơn, chúng tôi sẽ tạo lớp này dần dần. Đầu tiên, tạo chính lớp đó và thêm một phụ thuộc vào CustomerService:

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
Hãy giải thích các chú thích: @RestController nói với Spring rằng lớp này là một bộ điều khiển REST. Nói cách khác, lớp này thực hiện logic để xử lý các yêu cầu của máy khách. @Autowired nói với Spring rằng một phần phụ thuộc cần được thêm vào đây. Chúng tôi chuyển CustomerServicegiao diện cho hàm tạo. Trước đó, chúng tôi đã đánh dấu việc triển khai dịch vụ này bằng @Servicechú thích và bây giờ Spring sẽ có thể chuyển một thể hiện của việc triển khai này tới hàm tạo của bộ điều khiển. Tiếp theo, chúng tôi sẽ triển khai từng phương thức điều khiển để xử lý các hoạt động CRUD. Hãy bắt đầu với thao tác tạo. Để làm điều này, chúng tôi viết một createphương pháp:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
Hãy cùng phân tích phương thức này: @PostMapping(value = "/customers")có nghĩa là phương thức này xử lý các yêu cầu POST được gửi đến địa chỉ "/customers". Phương thức này trả về một tệp ResponseEntity<?>. A ResponseEntitylà một lớp đặc biệt để trả lại phản hồi. Sau đó, chúng tôi sẽ sử dụng nó để trả lại mã trạng thái HTTP cho máy khách. Phương thức có một @RequestBody Customer customertham số. Giá trị của tham số này đến từ phần thân yêu cầu. Các @RequestBodychú thích chỉ ra điều này. Bên trong phần thân của phương thức, chúng ta gọi create()phương thức trên dịch vụ đã tạo trước đó và chuyển nó cho bộ điều khiển khách hàng nhận được trong các tham số. Sau đó, chúng tôi trả về trạng thái "201 Đã tạo" bằng cách tạo một ResponseEntityđối tượng mới và chuyển HttpStatustrường enum tương ứng cho nó. Tiếp theo, chúng ta sẽ thực hiệnreadhoạt động: Đầu tiên, chúng tôi sẽ thực hiện hoạt động để có được danh sách tất cả các khách hàng có sẵn:

@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);
}
Hãy đi sâu vào: @GetMapping(value = "/customers")— mọi thứ ở đây tương tự như @PostMappingchú thích, nhưng hiện tại chúng tôi đang xử lý các yêu cầu GET. Lần này chúng tôi trả về a ResponseEntity<List<Customer>>và ngoài trạng thái HTTP, chúng tôi cũng sẽ trả về nội dung phản hồi, đây sẽ là danh sách khách hàng. Trong bộ điều khiển REST của Spring, mọi thứ đều là đối tượng POJO và tập hợp các đối tượng POJO, được trả về dưới dạng nội dung phản hồi và tự động được tuần tự hóa thành JSON, trừ khi có quy định khác. Điều này phù hợp với chúng tôi một cách hoàn hảo. Bên trong phương thức, chúng tôi sử dụng dịch vụ của mình để lấy danh sách tất cả khách hàng. Tiếp theo, nếu danh sách không rỗng và không trống, thì chúng ta sử dụngResponseEntityclass để trả về danh sách khách hàng và mã trạng thái HTTP "200 OK". Nếu không, chúng tôi chỉ cần trả lại mã trạng thái HTTP "404 Not Found". Bây giờ chúng tôi sẽ triển khai khả năng nhận khách hàng bằng ID của họ:

@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);
}
Một điều mới ở đây là biến đường dẫn. Biến được xác định trong URI: value = "/customers/{id}". Chúng tôi chỉ ra nó trong dấu ngoặc nhọn. Và chúng tôi nhận nó dưới intdạng tham số phương thức bằng cách sử dụng @PathVariable(name = "id")chú thích. Phương thức này sẽ chấp nhận các yêu cầu được gửi tới URI ở dạng /customers/{id}, trong đó {id}đại diện cho bất kỳ giá trị số nào. Giá trị này sau đó được chuyển qua int idbiến đến tham số phương thức. Trong phần thân, chúng tôi lấy Customerđối tượng bằng cách sử dụng dịch vụ của chúng tôi và nhận được id. Và sau đó, bằng cách tương tự với danh sách, chúng tôi trả về trạng thái "200 OK" và Customerchính đối tượng hoặc đơn giản là trạng thái "404 Không tìm thấy" nếu hệ thống không có khách hàng nào với điều đó id. Chúng ta vẫn cần thực hiện hai thao tác: cập nhật và xóa. Đây là mã cho các phương pháp này:

@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);
}
Về cơ bản không có gì mới trong các phương pháp này, vì vậy chúng tôi sẽ bỏ qua phần mô tả chi tiết. Điều đáng nói duy nhất là update()phương thức xử lý các yêu cầu PUT ( @PutMappingchú thích) và delete()phương thức xử lý các yêu cầu XÓA ( DeleteMappingchú thích). Đây là mã đầy đủ cho bộ điều khiển:

@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);
   }
}
Do đó, cấu trúc của dự án của chúng tôi như sau: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 7

Ra mắt và thử nghiệm

Để bắt đầu ứng dụng của chúng tôi, chỉ cần chạy main()phương thức trong RestExampleApplicationlớp. Nhưng để kiểm tra các dịch vụ web RESTful, chúng tôi cần tải xuống phần mềm bổ sung. Thực tế là các yêu cầu GET khá đơn giản để gửi từ một trình duyệt thông thường, nhưng một trình duyệt thông thường không thể gửi các yêu cầu POST, PUT và DELETE. Đừng lo lắng: bạn có thể sử dụng chương trình có tên Postman để gửi bất kỳ yêu cầu HTTP nào. Bạn có thể tải nó ở đây . Sau khi tải xuống và cài đặt Postman, chúng tôi bắt đầu thử nghiệm ứng dụng của mình. Để thực hiện việc này, hãy mở chương trình và tạo một yêu cầu mới: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 9Nhấp vào nút "Mới" ở góc trên bên trái. Tiếp theo, chọn "Yêu cầu": Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 10Tiếp theo, đặt tên cho nó và lưu lại. Bây giờ, hãy thử gửi yêu cầu POST đến máy chủ và tạo khách hàng đầu tiên: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 11Chúng tôi tạo ra một số khách hàng theo cách này. Sau đó, chúng tôi thay đổi loại yêu cầu thành GET và gửi yêu cầu đến máy chủ: Tổng quan về REST.  Phần 3: Xây dựng dịch vụ RESTful trên Spring Boot - 12

Bản tóm tắt

Chúc mừng! Chúng tôi đã bao phủ đầy đủ REST. Có một khối lượng lớn tài liệu, nhưng hy vọng nó hữu ích cho bạn:
  1. Chúng tôi đã học REST là gì.

  2. Chúng tôi đã tìm hiểu về cách REST ra đời.

  3. Chúng tôi đã nói về những hạn chế và nguyên tắc đằng sau phong cách kiến ​​trúc này:

    • kiến trúc máy khách-máy chủ
    • không quốc tịch
    • bộ nhớ đệm
    • giao diện thống nhất
    • lớp
    • mã theo yêu cầu (tùy chọn)
  4. Chúng tôi đã khám phá những lợi ích do REST cung cấp

  5. Chúng tôi đã kiểm tra chi tiết cách máy chủ và máy khách tương tác với nhau thông qua giao thức HTTP.

  6. Chúng tôi đã xem xét kỹ hơn các yêu cầu và phản hồi. Chúng tôi mổ xẻ các bộ phận cấu thành của họ.

  7. Cuối cùng, chúng tôi đã có một số kinh nghiệm thực tế bằng cách viết ứng dụng RESTful nhỏ của riêng mình bằng Spring Boot. Và chúng tôi thậm chí đã học cách kiểm tra nó bằng Postman.

Phù. Đó là rất nhiều, nhưng vẫn còn một cái gì đó để bạn làm như bài tập về nhà.

Bài tập về nhà

Hãy thử như sau:
  1. Theo mô tả ở trên, hãy tạo dự án Spring Boot của riêng bạn và triển khai logic tương tự như trong bài học. Lặp lại mọi thứ một cách chính xác.
  2. Chạy chương trình.
  3. Tải xuống và định cấu hình Postman (hoặc bất kỳ công cụ nào khác để gửi yêu cầu, chẳng hạn như curl).
  4. Kiểm tra các yêu cầu POST và GET theo cách tương tự được mô tả trong bài học.
  5. Tự kiểm tra các yêu cầu PUT và DELETE.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION