我们通过spring-boot(v1.3.3)使用spring数据rest,并通过标准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
}
例如,POST到/projects或PUT到/projects/s234会创建一个etag/版本为0的文档。另一个PUT到/projects/s234会覆盖文档,即使客户端没有提供版本/etag。此外,即使客户端没有提供版本/etag,/projects/s234上的DELETE也会删除文档。
如果并且仅当客户端提供有效的版本/etag时,我如何配置spring data rest来更新和删除文档?
neneneba API客户端需要在请求的头上指定一个有效的ETag,如下所示:
If-Match: <value of previous ETag>
通过将此标头添加到HTTP请求中,可以将其转换为条件操作,只有在满足条件时才会执行该条件操作。还有其他条件句,如If-None-Match
或If-Modified-Since
。
客户端负责添加条件标头。
根据这个问题,我理解您希望服务器禁止任何不提供有效ETag的操作,但据我所知,Spring Data Rest不支持这一点。
您可以更改客户端以包含正确的标头(假设它们在您的控制之下),也可以自己实现此功能。
您可以查看参考文档以了解更多信息。
如何强制客户端使用spring数据rest发送etag/version?
简单地说:你不能,除非你给客户写信。
如果并且仅当客户端提供有效的版本/etag时,我如何配置spring data rest来更新和删除文档?
这需要重写Spring Data Rest提供的PUT/DELETE/projects/s234处理程序,并自行处理ETag
为了覆盖处理程序,您需要使用RepositoryRestController对控制器进行注释,并在方法级别使用RequestMapping,以仍然受益于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参数)。