CodeGym /Java Blog /Toto sisi /REST 概述。第 3 部分:在 Spring Boot 上構建 RESTful 服務
John Squirrels
等級 41
San Francisco

REST 概述。第 3 部分:在 Spring Boot 上構建 RESTful 服務

在 Toto sisi 群組發布
這是我們對 REST 的概述的最後一部分。在前面的部分中,我們介紹了: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 1

創建項目

在本節中,我們將使用 Spring Boot 創建一個小型 RESTful 應用程序。我們的應用程序將對概述前一部分示例中的客戶實施 CRUD(創建、讀取、更新、刪除)操作。首先,我們將通過菜單創建一個新的 Spring Boot 應用程序:File -> New -> Project... 在打開的窗口中,選擇 Spring Initializr 並指定 Project SDK: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 2單擊“Next”按鈕。在下一個窗口中,指定“Maven Project”作為項目類型,指定“Group”和“Artifact”: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 3單擊“Next”按鈕。在下一個窗口中,我們需要選擇項目所需的 Spring Framework 組件。Spring Web 對我們來說已經足夠了: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 4單擊“下一步”按鈕。現在剩下的就是指示項目的名稱及其在文件系統中的位置: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 5單擊“完成”按鈕。項目創建完成,現在我們可以看到它的結構: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 6IDEARestExampleApplication為我們生成了一個Maven部署描述符(pom.xml)和應用程序的主類()。這是它們的樣子:

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>
休息示例應用程序:

@SpringBootApplication
public class RestExampleApplication {

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

}

創建 REST 功能

我們的應用程序是一個客戶管理系統。因此,我們需要做的第一件事是創建一個客戶實體。它將是一個 POJO(普通舊 Java 對象)類。在包內創建一個modelcom.codegym.lessons.rest_example。在包內model,創建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;
   }
}
該服務將對客戶實施 CRUD 操作。下一步是創建將實現這些操作的服務。在com.codegym.lessons.rest_example包中,創建一個service包。在裡面,創建一個CustomerService界面。下面是帶註釋的接口代碼:

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);
}
接下來,我們需要實現這個接口。現在一個Map<Integer, Customer>將存儲我們的客戶。地圖的鍵是客戶 ID,值是客戶本身。這樣做是為了不讓這個例子因使用真實數據庫的細節而超載。但是,將來我們將能夠編寫該接口的另一個實現,這將使連接到真實數據庫成為可能。在service包中,創建接口的實現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;
   }
}
註解@Service告訴 spring 這個類是一個服務。這是一種特殊類型的類,用於實現某些業務應用程序邏輯。隨後,由於這個註解,Spring 將使用依賴注入在所有需要它的地方為我們提供這個類的實例。現在是創建控制器的時候了。這是一個特殊的類,我們將在其中實現處理髮送到端點 (URI) 的客戶端請求的邏輯。為了使這一切更清楚,我們將逐步創建此類。首先,創建類本身並添加對以下內容的依賴CustomerService

@RestController
public class CustomerController {

   private final CustomerService customerService;

   @Autowired
   public CustomerController(CustomerService customerService) {
       this.customerService = customerService;
   }
}
讓我們解釋一下註解: @RestController告訴 Spring 這個類是一個 REST 控制器。換句話說,這個類實現了處理客戶端請求的邏輯。 @Autowired告訴 Spring 需要在這裡添加一個依賴。我們將接口傳遞CustomerService給構造函數。早些時候,我們用註釋標記了這個服務的實現@Service,現在 Spring 將能夠將這個實現的實例傳遞給控制器的構造函數。接下來,我們將實現每個控制器方法來處理 CRUD 操作。讓我們從創建操作開始。為此,我們編寫了一個create方法:

@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
   customerService.create(customer);
   return new ResponseEntity<>(HttpStatus.CREATED);
}
我們來分析一下這個方法: @PostMapping(value = "/customers")意思是這個方法處理髮送到地址“/customers”的POST請求。該方法返回一個ResponseEntity<?>. AResponseEntity是用於返迴響應的特殊類。稍後,我們將使用它向客戶端返回 HTTP 狀態代碼。該方法有一個@RequestBody Customer customer參數。該參數的值來自請求體。註釋@RequestBody表明了這一點。在方法體內,我們調用create()之前創建的服務的方法,並將其傳遞給接收到的參數中的客戶控制器。ResponseEntity然後我們通過創建一個新對象並將相應的HttpStatus枚舉字段傳遞給它來返回“201 Created”狀態。接下來,我們將實現read操作:首先,我們將實施操作以獲取所有可用客戶的列表:

@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")— 這裡的一切都與註解相似@PostMapping,但現在我們正在處理 GET 請求。這次我們返回一個ResponseEntity<List<Customer>>,除了 HTTP 狀態之外,我們還將返回一個響應主體,這將是客戶列表。在 Spring 的 REST 控制器中,一切都是 POJO 對象和 POJO 對象的集合,它們作為響應主體返回並自動序列化為 JSON,除非另有說明。這非常適合我們。在方法內部,我們使用我們的服務來獲取所有客戶的列表。接下來,如果列表不為 null 且不為空,則我們使用ResponseEntity返回客戶列表和“200 OK”HTTP 狀態代碼的類。否則,我們簡單地返回“404 Not Found”HTTP 狀態代碼。現在我們將實現使用其 ID 獲取客戶的能力:

@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);
}
這裡的一個新事物是路徑變量。該變量在 URI 中定義:value = "/customers/{id}"。我們用花括號表示它。我們int使用註釋將其作為方法參數接收@PathVariable(name = "id")。此方法將接受以 形式發送到 URI 的請求/customers/{id},其中{id}代表任何數值。該值隨後通過int id變量傳遞給方法參數。在正文中,我們Customer使用我們的服務和接收到的id. 然後,通過類比列表,我們返回“200 OK”狀態和對象Customer本身,或者如果系統沒有客戶,則返回“404 Not Found”狀態id。我們還需要實現兩個操作:更新和刪除。以下是這些方法的代碼:

@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);
}
這些方法本質上沒有什麼新東西,所以我們將跳過詳細描述。唯一值得一提的是update()方法處理PUT請求(@PutMapping註解),delete()方法處理DELETE請求(DeleteMapping註解)。這是控制器的完整代碼:

@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);
   }
}
因此,我們項目的結構如下: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 7

啟動和測試

要啟動我們的應用程序,只需運行類main()中的方法即可RestExampleApplication。但是要測試 RESTful Web 服務,我們需要下載額外的軟件。事實上,從普通瀏覽器發送 GET 請求非常簡單,但普通瀏覽器無法發送 POST、PUT 和 DELETE 請求。別擔心:您可以使用一個名為 Postman 的程序來發送任何 HTTP 請求。你可以在這裡下載。下載並安裝 Postman 後,我們開始測試我們的應用程序。為此,打開程序並創建一個新請求: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 9單擊左上角的“新建”按鈕。接下來,選擇“Request”: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 10接下來,為其命名並保存。現在讓我們嘗試向服務器發送 POST 請求並創建第一個客戶: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 11我們以這種方式創建了多個客戶。然後我們將請求類型改為GET,向服務器發送請求: REST 概述。 第 3 部分:在 Spring Boot 上構建 RESTful 服務 - 12

概括

恭喜!我們已經充分介紹了 REST。有大量的材料,但希望它對你有用:
  1. 我們了解了 REST 是什麼。

  2. 我們了解了 REST 是如何產生的。

  3. 我們談到了這種架構風格的局限性和背後的原則:

    • 客戶端-服務器架構
    • 無國籍的
    • 緩存
    • 統一接口
    • 圖層
    • 按需代碼(可選)
  4. 我們探索了 REST 提供的好處

  5. 我們詳細檢查了服務器和客戶端如何通過 HTTP 協議相互交互。

  6. 我們仔細研究了請求和響應。我們剖析了它們的組成部分。

  7. 最後,我們通過使用 Spring Boot 編寫自己的小型 RESTful 應用程序獲得了一些實踐經驗。我們甚至學會瞭如何使用 Postman 對其進行測試。

呸。那是很多,但是您仍然需要做一些功課。

家庭作業

嘗試以下操作:
  1. 按照上面的描述,創建您自己的 Spring Boot 項目並實現與課程中相同的邏輯。完全重複一切。
  2. 啟動應用程序。
  3. 下載並配置 Postman(或任何其他用於發送請求的工具,例如 curl)。
  4. 按照課程中描述的相同方式測試 POST 和 GET 請求。
  5. 自己測試 PUT 和 DELETE 請求。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION