我们通过spring boot(v1.3.3)使用spring数据休息,并通过标准REST Repository Exporter公开以下实体:
@Document
public class Project {
@Version
private Long version;
@CreatedDate
private LocalDateTime createdDate;
@CreatedBy
private String createdBy;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@LastModifiedBy
private String lastModifiedBy;
private String name;
//getters and setters omitted
}
/例如/ project或PUT到/ projects / 1234的POST会创建一个带有etag /版本0的文档。即使客户端没有提供版本/ etag,/ projects / 1234的另一个PUT也会覆盖文档。此外,即使客户端未提供版本/ etag,/ projects / 1234上的DELETE也会删除该文档。
当且仅当客户端提供有效版本/ etag时,如何配置spring data rest以更新和删除文档?
答案 0 :(得分:3)
API 客户端需要在请求中的标头上指定有效的ETag,如下所示:
If-Match: <value of previous ETag>
通过将此标头添加到HTTP请求,您可以将其转换为条件操作,只有在满足条件时才会执行该操作。还有其他条件,例如If-None-Match
或If-Modified-Since
。
客户端负责添加条件标头。
从我理解的问题中,您希望服务器禁止任何不提供有效ETag的操作,但据我所知Spring Data Rest不支持此操作。
您可以更改客户端以包含正确的标头(假设它们在您的控制之下),或者您自己实现此功能。
您可以查看Reference Documentation了解更多信息。
答案 1 :(得分:2)
如何强制客户端使用spring数据休息发送etag / version?
简单地说:你不能,除非你写客户。
当且仅当客户端提供有效版本/ etag时,如何配置spring data rest以更新和删除文档?
这需要覆盖Spring Data Rest提供的 PUT / DELETE / projects / 1234 处理程序,并自行处理ETag。
为了覆盖处理程序,您需要使用RepositoryRestController注释控制器并使用RequestMapping at the method level仍然可以从Spring提供的其他处理程序中受益。
要处理ETag部分,您可以深入了解请求标头的内容(通过向处理程序添加HttpServletRequest参数来搜索@ESala提到的If- *标头。
@RepositoryRestController
public class ProjectRepositoryRestController {
@Autowired
private ProjectRepository repository;
@RequestMapping(value = "/projects/{id}", method = RequestMethod.PUT)
@ResponseBody
public Item update(@PathVariable(value = "id") String id, @RequestBody Project, HttpServletRequest request)
{
/* dig into the request headers */
// for instance
String header = request.getHeader("If-match");
// or more likely do something with request.getHeaders(...) or request.getHeaderNames(...) to check if the relevant headers are present.
/* apply your logic on Etags */
if (null == header) {
throw new ARelevantException();
}
/* go on with the processing of the request if everything is OK */
Project project = repository.findOne(id);
/* perform some magic with your entity and your input data */
project = repository.save(project);
return project;
}
}
要处理标题,可以使用其他选项,例如使用RequestHeader注释。您还可以查看RequestEntity以立即获取请求正文和标题(只是不要混合RequestEntity参数和@RequestBody + @RequestHeader参数)。