1. 概述
在本教程中,我們將研究兩個重要的 HTTP 方法,PUT 和 POST,這些方法在 REST 架構中被我們頻繁使用。 開發者在設計 RESTful Web 服務時,有時會為選擇這兩種方法而苦惱,這一點無需贅述。 因此,我們將通過在 Spring Boot 中實現一個簡單的 RESTful 應用來解決這個問題。
2. PUT 與 POST 的困境
在典型的 REST 架構中,客户端通過 HTTP 方法向服務器發送請求,用於創建、檢索、修改或刪除資源。雖然我們可以使用 PUT 和 POST 兩種方法來創建資源,但它們在用途上存在顯著差異。
根據 RFC 2616 標準,POST 方法應用於請求服務器將包含的實體作為現有資源的子級接受。這意味着 POST 方法調用將創建一個子資源,位於資源集合下。
相反,PUT 方法應用於請求服務器將包含的實體存儲在提供的 Request-URI 下。如果 Request-URI 指向服務器上已存在的資源,則提供的實體將被視為現有資源的修改版本。因此,PUT 方法調用將要麼創建一個新的資源,要麼更新一個現有資源。
另一個重要的區別是,PUT 是一種冪等方法,而 POST 不是。例如,多次調用 PUT 方法將要麼創建一個新的資源,要麼更新同一個資源。與之相反,多次 POST 請求將導致相同的資源被創建多次。
3. 示例應用程序
為了演示 PUT 和 POST 方法之間的區別,我們將使用 Spring Boot 創建一個簡單的 RESTful Web 應用程序。該應用程序將存儲人們的姓名和地址。
3.1. Maven 依賴
首先,我們需要在我們的 pom.xml文件中添加 Spring Web、Spring Data JPA 和內存數據庫 H2 的依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>3.2. 領域實體與存儲接口
首先,我們創建領域對象。對於通訊錄,我們將定義一個名為 Address 的 Entity 類,用於存儲個人的地址信息。為了簡化起見,我們的 Address 實體將包含 name(姓名)、city(城市)和 postalCode(郵政編碼)這三個字段:
@Entity
public class Address {
private @Id @GeneratedValue Long id;
private String name;
private String city;
private String postalCode;
// constructors, getters, and setters
}下一步是訪問數據庫中的數據。為了簡化操作,我們將利用 Spring Data JPA 的 JpaRepository,這允許我們在不編寫任何額外代碼的情況下執行 CRUD 功能:
public interface AddressRepository extends JpaRepository<Address, Long> {
}3.3. REST 控制器
最後,我們需要為我們的應用程序定義 API 端點。我們將創建一個 RestController,它將從客户端消耗 HTTP 請求並返回適當的響應。
在這裏,我們將 定義一個 @PostMapping 用於創建新的地址並將其存儲在數據庫中,以及一個 @PutMapping 用於根據請求 URI 更新地址簿的內容。如果未找到 URI,則將創建一個新地址並將其存儲在數據庫中:
@RestController
public class AddressController {
private final AddressRepository repository;
AddressController(AddressRepository repository) {
this.repository = repository;
}
@PostMapping("/addresses")
Address createNewAddress(@RequestBody Address newAddress) {
return repository.save(newAddress);
}
@PutMapping("/addresses/{id}")
Address replaceEmployee(@RequestBody Address newAddress, @PathVariable Long id) {
return repository.findById(id)
.map(address -> {
address.setCity(newAddress.getCity());
address.setPin(newAddress.getPostalCode());
return repository.save(address);
})
.orElseGet(() -> {
return repository.save(newAddress);
});
}
//additional methods omitted
}3.4. cURL 請求
現在我們可以使用 cURL 向我們的服務器發送示例 HTTP 請求來測試我們開發的應用程序。
對於創建新地址,我們將數據包含在 JSON 格式中,並通過 POST 請求發送:
curl -X POST --header 'Content-Type: application/json' \
-d '{ "name": "John Doe", "city": "Berlin", "postalCode": "10585" }' \
http://localhost:8080/addresses現在讓我們更新我們創建的地址的內容。我們將使用 URL 中的 id 發送一個 PUT 請求。在本例中,我們將更新我們剛剛創建的地址的 city 和 postalCode 部分。我們假設它已保存為 id = 1:
curl -X PUT --header 'Content-Type: application/json' \
-d '{ "name": "John Doe", "city": "Frankfurt", "postalCode": "60306" }' \
http://localhost:8080/addresses/14. 結論
在本文中,我們探討了 HTTP 方法 PUT 和 POST 的概念差異。此外,我們還學習瞭如何使用 Spring Boot 框架為開發 RESTful 應用程序實現這些方法。
綜上所述,我們應該使用 POST 方法來創建新的資源,使用 PUT 方法來更新現有資源。