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 依賴項
首先,我們需要包含 Spring Web、Spring Data JPA 和內存 H2 數據庫的依賴項,添加到我們的 pom.xml 文件中:
<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. 域實體和存儲接口
我們首先創建一個域對象。對於地址簿,我們將定義一個 Entity 類 Address,用於存儲個人的地址信息。為了簡化,我們將使用三個字段,name、city 和 postalCode,用於我們的 Address 實體:
@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
現在讓我們更新我們創建的地址的內容。我們將通過 PUT 請求使用地址的 id 在 URL 中,在此示例中,我們將更新地址的 city 和 postalCode 部分。我們假設它已保存為 id=1:
curl -X PUT --header 'Content-Type: application/json' \
-d '{ "name": "John Doe", "city": "Frankfurt", "postalCode": "60306" }' \
http://localhost:8080/addresses/1
4. 結論
在本文中,我們討論了 HTTP 方法 PUT 和 POST 的概念差異。此外,我們還學習瞭如何使用 Spring Boot 框架開發 RESTful 應用程序,並利用這些方法實現。
總之,我們應該使用 POST 方法創建新的資源,使用 PUT 方法更新現有資源。