REST PUT操作检测陈旧对象、规避更新冲突的最佳实践
REST中避免PUT操作意外覆盖的成熟方案
REST架构中完全有成熟的标准方案解决你描述的“更新丢失”冲突问题,并非普遍忽略这类场景,核心机制是ETag实体标签配合If-Match请求头,这是RFC 9110定义的HTTP标准实践。
具体流程
- 客户端通过GET请求获取资源时,服务器在响应头中返回
ETag:这是服务器生成的唯一标识当前资源版本的字符串,客户端不可修改,且不会破坏PUT的幂等性 - 客户端发起PUT(或POST/DELETE)更新请求时,在请求头中携带
If-Match字段,值为之前GET到的ETag - 服务器处理请求时,对比当前资源的最新ETag与
If-Match中的值:- 匹配则执行更新操作,同时生成新的ETag返回给客户端
- 不匹配则返回
419 Conflict状态码,拒绝请求,提示客户端当前操作的是陈旧版本
RFC 9110官方定义
If-Match最常用于状态变更方法(如POST、PUT、DELETE),以防止多个用户代理并行操作同一资源时的意外覆盖(即避免‘更新丢失’问题)。通常,若所选表示的当前实体标签不在If-Match字段值中,可中止涉及表示选择或修改的请求。
Spring框架的便捷实现
对于使用Spring框架的开发者,Spring Data REST提供了开箱即用的支持:
- 在实体类的版本字段上添加
@Version注解(对应数据库的版本号字段) - Spring会自动为GET请求生成并返回ETag响应头
- 当客户端发起PUT请求时,Spring会自动校验
If-Match头中的ETag是否与资源当前版本匹配,不匹配则直接返回419 Conflict,无需手动编写校验逻辑
内容的提问来源于stack exchange,提问作者Adam Wise
相关产品推荐
相关产品推荐

