我正在使用Spring Boot和Spring REST。我想了解HTTP PATCH方法来更新我的Model的属性
是否有任何好的教程解释如何使其工作?
我注意到许多提供的答案都是JSON补丁或不完整的答案。以下是功能真实代码所需内容的完整说明和示例
首先,PATCH是一种选择性PUT。您可以使用它来更新对象或对象列表的任意数量的字段。在PUT中,您通常会使用任何更新发送整个对象。
PATCH / object / 7
{
"objId":7,
"objName": "New name"
}
PUT / object / 7
{
"objId":7,
"objName": "New name",
"objectUpdates": true,
"objectStatus": "ongoing",
"scoring": null,
"objectChildren":[
{
"childId": 1
},
............
}
这允许您更新没有大量端点的记录。例如,在上面,要更新评分,您需要object / {id} / scoring,然后更新名称,您需要object / {id} / name。每个项目的字面意思是一个端点,或者您需要前端为每次更新发布整个对象。如果您有一个巨大的对象,这可能需要大量的网络时间或不必要的移动数据。该补丁允许您拥有1个端点,其中包含移动平台应使用的最小对象属性发送。
这是一个真实世界用于补丁的例子:
@ApiOperation(value = "Patch an existing claim with partial update")
@RequestMapping(value = CLAIMS_V1 + "/{claimId}", method = RequestMethod.PATCH)
ResponseEntity<Claim> patchClaim(@PathVariable Long claimId, @RequestBody Map<String, Object> fields) {
// Sanitize and validate the data
if (claimId <= 0 || fields == null || fields.isEmpty() || !fields.get("claimId").equals(claimId)){
return new ResponseEntity<>(HttpStatus.BAD_REQUEST); // 400 Invalid claim object received or invalid id or id does not match object
}
Claim claim = claimService.get(claimId);
// Does the object exist?
if( claim == null){
return new ResponseEntity<>(HttpStatus.NOT_FOUND); // 404 Claim object does not exist
}
// Remove id from request, we don't ever want to change the id.
// This is not necessary, you can just do it to save time on the reflection
// loop used below since we checked the id above
fields.remove("claimId");
fields.forEach((k, v) -> {
// use reflection to get field k on object and set it to value v
// Change Claim.class to whatver your object is: Object.class
Field field = ReflectionUtils.findField(Claim.class, k); // find field in the object class
field.setAccessible(true);
ReflectionUtils.setField(field, claim, v); // set given field for defined object to value V
});
claimService.saveOrUpdate(claim);
return new ResponseEntity<>(claim, HttpStatus.OK);
}
对于某些人而言,上述情况可能会令人困惑,因为较新的开发人员通常不会像这样处理反射。基本上,无论您在正文中传递此函数,它都会使用给定的ID找到关联的声明,然后仅将您传入的字段更新为键值对。
示例正文:
PATCH / Claims / 7
{
"claimId":7,
"claimTypeId": 1,
"claimStatus": null
}
以上内容将claimTypeId和claimStatus更新为权利要求7的给定值,保持所有其他值不变。
所以回报将是这样的:
{
"claimId": 7,
"claimSrcAcctId": 12345678,
"claimTypeId": 1,
"claimDescription": "The vehicle is damaged beyond repair",
"claimDateSubmitted": "2019-01-11 17:43:43",
"claimStatus": null,
"claimDateUpdated": "2019-04-09 13:43:07",
"claimAcctAddress": "123 Sesame St, Charlotte, NC 28282",
"claimContactName": "Steve Smith",
"claimContactPhone": "777-555-1111",
"claimContactEmail": "[email protected]",
"claimWitness": true,
"claimWitnessFirstName": "Stan",
"claimWitnessLastName": "Smith",
"claimWitnessPhone": "777-777-7777",
"claimDate": "2019-01-11 17:43:43",
"claimDateEnd": "2019-01-11 12:43:43",
"claimInvestigation": null,
"scoring": null
}
正如您所看到的,完整对象将返回而不会更改除要更改的内容之外的任何数据。我知道这里的解释有点重复,我只是想清楚地勾勒出来。
就PATCH
和PUT
而言,POST
方法没有任何本质上的不同。挑战在于您传递PATCH请求以及如何在Controller中映射数据。如果使用@RequestBody
映射到值bean,则必须计算实际设置的值和空值的含义。其他选项是将PATCH
请求限制为一个属性并在url中指定它或将值映射到Map
。另见Spring MVC PATCH method: partial updates
使用 - 创建一个休息模板
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
RestTemplate rest = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
now make the PATCH call
ResponseEntity<Map<String, Object>> response = rest.exchange(api, HttpMethod.PATCH, request,
responseType);