【问题标题】:Spring REST and PATCH methodSpring REST 和 PATCH 方法
【发布时间】:2015-07-11 09:38:17
【问题描述】:

我正在使用 SpringBoot 和 Spring REST。 我想了解更新模型属性的 HTTP PATCH 方法

有没有什么好的教程解释如何使它工作?

  • 要发送的 HTTP PATCH 方法和正文
  • 控制器方法以及如何管理更新操作

【问题讨论】:

  • 聚会有点晚了:我在post 中汇总了有关如何使用PATCH 的一些细节。这篇文章中描述的方法在 GitHub 上的 example 中使用。

标签: spring spring-boot spring-rest


【解决方案1】:

我注意到许多提供的答案都是 JSON 补丁或不完整的答案。下面是一个完整的解释和示例,说明您需要运行真实世界的代码

首先,PATCH 是一个选择性 PUT。您可以使用它来更新对象或对象列表的任意数量的字段。在 PUT 中,您通常会发送带有任何更新的整个对象。

补丁/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,然后要更新 name,您需要 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 找到相关的声明,然后只更新你作为键值对传递的字段。

示例正文:

补丁 /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": "steve.smith@domain.com",
   "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
}

如您所见,完整的对象将返回,而不会更改您想要更改的数据以外的任何数据。我知道这里的解释有点重复,我只是想清楚地概述它。

【讨论】:

  • 很好地使用反射来做到这一点。击败了我在其他地方看到的每个字段的所有空检查。
  • 是的,这种类型的空检查想法让我发疯。这感觉像是一种廉价的解决方法,它生成了太多代码来完成预期很简单的事情。
【解决方案2】:

就 Spring 而言,PATCH 方法与 PUTPOST 没有本质上的不同。挑战在于您在 PATCH 请求中传递的内容以及如何在 Controller 中映射数据。如果您使用@RequestBody 映射到您的值bean,您将不得不弄清楚实际设置的内容以及空值的含义。其他选项是将PATCH 请求限制为一个属性并在url 中指定它或将值映射到Map。 另见Spring MVC PATCH method: partial updates

【讨论】:

  • PATCH example.com/api/entity/1 HTTP/1.1 是否有任何实用程序类可以理解操作/路径元素?内容类型:application/json-patch+json [ { "op": "replace", "path": "aBoolean", "value": true } ]
【解决方案3】:

使用 - 创建一个休息模板

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);

【讨论】:

  • 这解释了如何从客户端进行 PATCH 调用,但问题是关于如何处理服务器上的调用。
猜你喜欢
  • 2017-12-25
  • 2017-02-16
  • 1970-01-01
  • 2018-01-08
  • 2015-06-15
  • 1970-01-01
  • 2015-01-05
  • 2017-03-14
  • 1970-01-01
相关资源
最近更新 更多