我有一个项目,我使用Spring MVC + Jackson来构建REST服务.假设我有以下java实体
public class MyEntity {
private Integer id;
private boolean aBoolean;
private String aVeryBigString;
//getter & setters
}
Run Code Online (Sandbox Code Playgroud)
有时候,我只是想更新布尔值,我不认为用更大的字符串发送整个对象只是为了更新一个简单的布尔值.所以,我考虑过使用PATCH HTTP方法只发送需要更新的字段.所以,我在我的控制器中声明了以下方法:
@RequestMapping(method = RequestMethod.PATCH)
public void patch(@RequestBody MyVariable myVariable) {
//calling a service to update the entity
}
Run Code Online (Sandbox Code Playgroud)
问题是:我如何知道哪些字段需要更新?例如,如果客户端只想更新布尔值,我将得到一个空的"aVeryBigString"对象.我怎么知道用户只想更新布尔值,但不想清空字符串?
我通过构建自定义URL"解决"了这个问题.例如,以下URL:POST/myentities/1/aboolean/true将映射到只允许更新布尔值的方法.此解决方案的问题在于它不符合REST.我不希望100%兼容REST,但我不愿意提供自定义URL来更新每个字段(特别是考虑到当我想更新多个字段时它会导致问题).
另一个解决方案是将"MyEntity"拆分为多个资源并只更新这些资源,但我觉得它没有意义:"MyEntity" 是一个普通资源,它不是由其他资源组成的.
那么,有一种解决这个问题的优雅方式吗?
默认情况下,当我们有一个暴露了save方法的存储库时,我们可以执行PATCH请求.然后,Spring Data REST从数据库中检索原始对象并将更改应用于实体,然后将其保存给我们(在JsonPatchHandler类中).这允许我们为类做以下请求
class Address {
Long id;
String street;
Long houseNumber;
}
Run Code Online (Sandbox Code Playgroud)
PATCH/api /地址/ 1与身体
{ houseNumber: 123 }
Run Code Online (Sandbox Code Playgroud)
只有这一个领域才会改变.
现在有了自定义控制器,我们希望在update方法中接收整个对象(在HATEOAS将其与来自DB的原始对象合并之后)
@RepositoryRestController
@ExposesResourceFor(Address.class)
@ResponseBody
@RequestMapping("/addresses")
public class AdddressController {
@PatchMapping("/{addressId}")
public Resource<Address> update(@RequestBody Resource<Address> addressResource, @PathVariable Long addressId) {
Address address= addressResource.getContent();
// .... some logic
address = addressRepository.save(address);
return new Resource<>(address);
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,在我会做一些逻辑的地方,我得到的地址是空字段而不是合并对象.
是否可以在Spring Data REST堆栈中插入自定义控制器,以便在修补请求时将它合并为我(就像它对普通存储库一样)?
编辑:我想找到一个透明地与PATCH(内容类型:application/json-patch + json)和PATCH(内容类型:application/hal + json)一起工作的解决方案