如何强制客户端使用spring数据rest发送etag/version



我们通过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-MatchIf-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参数)。

最新更新