你如何在REST中实现粗粒度乐观锁?

8
我已经为我的REST资源实现了乐观锁,这些资源与数据库表具有一对一的映射关系,通过将在GET请求中返回的版本号传回到PUT请求中。如果在我执行GET和PUT之间数据库中的版本号发生更改,则会发生乐观锁异常。这是一个相当简单的设计。
现在,如何为映射到多个数据库表的复合REST资源实现相同的操作呢?我不想传回多个版本字段(每个与复合资源相关的数据表都需要一个版本字段)。复合资源的一个简单示例是/FooBar,其中/Foo和/Bar是非复合资源。
我基本上正在寻找Fowler Coarse Grained Locking模式的REST实现示例:http://martinfowler.com/eaaCatalog/coarseGrainedLock.html

在您的REST服务中,您可以只收集版本并将它们放入一个由表示版本的唯一生成ID作为键的Map中吗?然后将其发送给客户端,并在编辑后让他们将其发送回给您?然后,您可以使用该ID获取实体图的版本。 - robert_difalco
1个回答

5
这就是 ETag 头 的设计初衷。实现该方法的一种常见方式是生成响应数据,对其进行哈希(无需安全性保证,只要低碰撞),并将该哈希用作 ETag 值。请注意,此方法忽略了生成响应所涉及的源数量。
然后,客户端会在 If-Match 头中发送收到的 ETag,服务器可以使用它来检查请求的新鲜度。

如果数据不够“新鲜”,HTTP服务器会发送409(冲突)状态码 - Aurélien Bénel
412实际上是HTTP状态码。请参见http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-21#section-3.1。 - fumanchu
嗯,有趣。那么规范就比较宽松了,因为409中的示例非常明确:“例如,如果正在使用版本控制,并且被PUT的实体包含与早期(第三方)请求所做的更改冲突的资源更改,则服务器可能使用409响应表示无法完成请求”。 - Aurélien Bénel
1
是的,但您会注意到ETag和If-Match没有在那里提到。 409适用于任何未由ETag编码的冲突。请注意,该方法允许PUT更新文档的一部分,如果它不是先前请求更改的相同部分,则服务器可以继续合并它们而不出错。使用ETag / If-Match无法做到这一点,因为它是一个“整个文档”的大锤。 - fumanchu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接