在自定义Spring MVC控制器中支持HTTP PATCH的最佳实践是什么?特别是在使用HATEOAS/HAL时?是否有一种更简单的方法来合并对象,而不必检查请求json中每个字段的存在(或编写和维护dto),理想情况下是自动解组到资源的链接?
我知道这个功能存在于Spring Data Rest中,但是有可能利用它在自定义控制器中使用吗?
我不认为您可以在这里使用spring-data-rest功能。
spring-data-rest在内部使用json-patch库。基本上,我认为工作流程如下:
- 读取您的实体 使用objectMapper将其转换为json
- 应用补丁(这里你需要json-patch)(我认为你的控制器应该采取JsonPatchOperation列表作为输入)
- 将打过补丁的json合并到你的实体中
我认为困难的部分是第四点。但如果你不需要一个通用的解决方案,这可能会更容易。
如果你想了解spring-data-rest的作用,看看org.springframework.data.rest.webmvc.config.JsonPatchHandler
编辑
spring-data-rest中的补丁机制在最新版本中发生了显著变化。最重要的是,它不再使用json-patch库,现在从头开始实现json补丁支持。
我可以设法在自定义控制器方法中重用主要补丁功能。
下面的代码片段演示了基于spring-data-rest 2.6 的方法 import org.springframework.data.rest.webmvc.IncomingRequest;
import org.springframework.data.rest.webmvc.json.patch.JsonPatchPatchConverter;
import org.springframework.data.rest.webmvc.json.patch.Patch;
//...
private final ObjectMapper objectMapper;
//...
@PatchMapping(consumes = "application/json-patch+json")
public ResponseEntity<Void> patch(ServletServerHttpRequest request) {
MyEntity entityToPatch = someRepository.findOne(id)//retrieve current state of your entity/object to patch
Patch patch = convertRequestToPatch(request);
patch.apply(entityToPatch, MyEntity.class);
someRepository.save(entityToPatch);
//...
}
private Patch convertRequestToPatch(ServletServerHttpRequest request) {
try {
InputStream inputStream = new IncomingRequest(request).getBody();
return new JsonPatchPatchConverter(objectMapper).convert(objectMapper.readTree(inputStream));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}