RESTful API 中的 PUT 和 POST 请求
1、概览
在设计 RESTful API 的时候,往往会纠结于到底是用 PUT 还是 POST 请求?
本文将会带你了解在 RESTful API 中 PUT 和 POST 请求之间的区别以及它们的应用场景。
2、PUT 与 POST
在典型的 REST 架构中,客户端以 HTTP 方法的形式向服务器发送请求,以创建、检索、修改或删除资源。虽然可以使用 PUT
和 POST
来创建资源,但它们在预期应用方面有很大的不同。
根据 RFC 2616 标准,POST 方法应该用于请求服务器将所附实体作为现有资源(由请求 URI 标识)的子级接受。这意味着使用 POST 方法调用将在资源集合下创建一个子资源。
相反,PUT 方法应该用于请求服务器将所附实体存储在请求的 URI 下。如果请求 URI 指向服务器上的现有资源,则提供的实体将被视为现有资源的修改版本。因此,PUT 方法调用要么创建一个新资源,要么更新现有资源。
这两种方法的另一个重要区别是,PUT 是一种幂等方法,而 POST 不是。例如,多次调用 PUT 方法将创建或更新同一资源。相比之下,多次 POST 请求将导致多次创建同一资源。
3、示例应用
使用 Spring Boot 创建一个简单的 RESTful Web 应用来演示 PUT 和 POST 请求的区别。
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、实体和 Repository 接口
创建 Address
实体类,包含三个字段 name
、city
和 postalCode
。
@Entity
public class Address {
private @Id @GeneratedValue Long id;
private String name;
private String city;
private String postalCode;
// 构造函数、get、set 方法省略
}
创建 AddressRepository
Repository,继承自 JpaRepository
接口:
public interface AddressRepository extends JpaRepository<Address, Long> {
}
3.3、REST Controller
最后,创建 RestControlle
。定义一个 @PostMapping
端点用于创建新的 Address
并将其存储到数据库中,以及一个 @PutMapping
端点用于根据请求 URI 更新 Address
。如果未找到 URI,则创建一个新的 Address
并将其存储到数据库中:
@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);
});
}
}
3.4、cURL 请求
现在,使用 cURL 向服务器发送 HTTP 请求来测试我们开发的应用。
使用 POST 请求创建新的 Address
:
curl -X POST --header 'Content-Type: application/json' \
-d '{ "name": "John Doe", "city": "Berlin", "postalCode": "10585" }' \
http://localhost:8080/addresses
接着,更新已创建的 Address
,在 URL 中使用其 id
发送 PUT 请求。
在本例中,更新刚刚创建的 Address
中的 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 请求用于创建或者更新资源,如果资源不存在就创建,如果资源存着就更新,所以 PUT 请求是幂等的。
Ref:https://www.baeldung.com/rest-http-put-vs-post