概览
本文将详细介绍HTTP PUT与PATCH的区别及使用场景,并给出示例代码。
什么时候用?
当用户需要修改对象所有数据时,应当使用PUT。
当用户只需要修改对象部分数据时,应当使用PATCH。
事实上,如果只需修改对象少数字段,却采用PUT,会显得笨拙而占用带宽,应当避免。
PUT和PATCH实例
假如我们要用REST API修改HeavyResource的多个字段。
public class HeavyResource {
private Integer id;
private String name;
private String address;
// ...
我们可以用PUT方式创建一个可以修改对象所有字段的方法
@PutMapping("/heavyresource/{id}")
public ResponseEntity<?> saveResource(@RequestBody HeavyResource heavyResource,
@PathVariable("id") String id) {
heavyResourceRepository.save(heavyResource, id);
return ResponseEntity.ok("resource saved");
}
如果只有address字段经常被客户修改,那我们就不需要传输整个heavyResource对象,而是采用PATC方法仅传输address字段数据。
我们创建HeavyResourceAddressOnly 来举例。
public class HeavyResourceAddressOnly {
private Integer id;
private String address;
// ...
}
现在我们来实现PATCH部分更新:
@PatchMapping("/heavyresource/{id}")
public ResponseEntity<?> partialUpdateName(
@RequestBody HeavyResourceAddressOnly partialUpdate, @PathVariable("id") String id) {
heavyResourceRepository.save(partialUpdate, id);
return ResponseEntity.ok("resource address updated");
}
通过PATCH,我们不需要传递整个对象数据,而仅需要传递部分需要修改的字段即可。
幂等性
HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。
-
GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123,不会改变资源的状态,不论调用一次还是N次都没有副作用。
-
DELETE方法满足幂等性。比如:DELETE http://www.forum.com/article/123,调用一次和N次对系统产生的副作用是相同的,即删掉了id为123的帖子。
-
POST多次调用会产生不同结果,所以是非幂等的。比如:创建一个用户,由于网络原因或是其他原因多创建了几次,那么将会有多个用户被创建。
-
PUT多次调用结果一样,是幂等的。比如PUT id/123会创建一个id为123的用户,多次调用还是会创建的结果是一样的。
-
PATCH是非幂等的。示例如下:
a.假设请求GET /users,返回users的集合。
[{ “id”: 1, “username”: “firstuser”, “email”: “firstuser@example.org” }]b.现在我们发送请求PATCH /users,进行更新操作(为该集合添加一个元素)
[{ “username”: “newuser”, “email”: “newuser@example.org” }]c.再次请求GET /users
[
{ “id”: 1, “username”: “firstuser”, “email”: “firstuser@example.org” },
{ “id”: 2, “username”: “newuser”, “email”: “newuser@example.org” }
]d.重复第二步操作,现在的结果(假设用户名可重复):
[
{ “id”: 1, “username”: “firstuser”, “email”: “firstuser@example.org” },
{ “id”: 2, “username”: “newuser”, “email”: “newuser@example.org” },
{ “id”: 3, “username”: “newuser”, “email”: “newuser@example.org” }
]