此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Data REST 4.4.0! |
带标头的条件操作
本节介绍 Spring Data REST 如何使用标准 HTTP 标头来提高性能、条件化操作并为更复杂的前端做出贡献。
ETag
、 和 HeadersIf-Match
If-None-Match
ETag
标头提供了一种标记资源的方法。这可以防止客户端相互覆盖,同时还可以减少不必要的调用。
请考虑以下示例:
class Sample {
@Version Long version; (1)
Sample(Long version) {
this.version = version;
}
}
1 | 注释(如果您使用的是 Spring Data JPA,则为 JPA 注释,所有其他模块为 Spring Data 注释)将此字段标记为版本标记。@Version org.springframework.data.annotation.Version |
前面示例中的 POJO 在由 Spring Data REST 作为 REST 资源提供时,具有一个带有version字段值的 Headers。ETag
如果我们提供如下标头,我们可以有条件地 , , 或该资源:PUT
PATCH
DELETE
If-Match
curl -v -X PATCH -H 'If-Match: <value of previous ETag>' ...
仅当资源的当前状态与标头匹配时,才会执行操作。这种保护措施可以防止客户端相互STOMP踏。两个不同的客户端可以获取资源并具有相同的 .如果一个客户端更新资源,则会在响应中获得 new。但是第一个客户端仍然具有旧的标头。如果该客户端尝试使用标头进行更新,则更新将失败,因为它们不再匹配。相反,该客户端会收到要发回的 HTTP 消息。然后,客户可以赶上,但这是必要的。ETag
If-Match
ETag
ETag
If-Match
412 Precondition Failed
术语“版本”可能具有不同的语义,具有不同的数据存储,甚至在您的应用程序中具有不同的语义。Spring Data REST 有效地委托给数据存储的元模型,以识别字段是否进行了版本控制,如果是,则仅在元素匹配时才允许列出的更新。ETag |
If-None-Match
标头提供了另一种选择。允许条件查询,而不是条件更新。请考虑以下示例:If-None-Match
curl -v -H 'If-None-Match: <value of previous etag>' ...
前面的命令(默认情况下)运行 .Spring Data REST 在执行 .如果标头与 ETag 匹配,则它会得出结论,即没有任何更改,并且不会发送资源的副本,而是发回 HTTP 状态代码。从语义上讲,它显示为“如果此提供的标头值与服务器端版本不匹配,请发送整个资源。否则,不要发送任何东西。GET
If-None-Match
GET
304 Not Modified
此 POJO 来自基于 的单元测试,因此它没有 (JPA) 或 (MongoDB) 注释,这在应用程序代码中是预期的。它只关注 field with 如何产生 header。ETag @Entity @Document @Version ETag |
If-Modified-Since
页眉
If-Modified-Since
标头提供了一种检查资源自上次请求以来是否已更新的方法,这使应用程序可以避免重新发送相同的数据。请考虑以下示例:
@Document
public class Receipt {
public @Id String id;
public @Version Long version;
public @LastModifiedDate Date date; (1)
public String saleItem;
public BigDecimal amount;
}
1 | Spring Data Commons 的注释允许以多种格式(JodaTime的、遗留的 Java 和 JDK8 日期/时间类型和 /)捕获此信息。@LastModifiedDate DateTime Date Calendar long Long |
对于前面示例中的日期字段, Spring Data REST 返回类似于以下内容的 Headers:Last-Modified
Last-Modified: Wed, 24 Jun 2015 20:28:15 GMT
可以捕获此值并将其用于后续查询,以避免在未更新时两次获取相同的数据,如下例所示:
curl -H "If-Modified-Since: Wed, 24 Jun 2015 20:28:15 GMT" ...
使用上述命令,您要求仅在资源自指定时间以来发生更改时才获取资源。如果是这样,您将获得一个修改后的标头,用于更新客户端。否则,您将收到 HTTP 状态代码。Last-Modified
304 Not Modified
标头的格式完美,可以发回以供将来查询。
不要将标头值与不同的查询混合和匹配。结果可能是灾难性的。仅在请求完全相同的 URI 和参数时使用标头值。 |
构建更高效的前端
ETag
元素与 AND 标头相结合,让您构建一个对消费者的数据计划和移动电池寿命更友好的前端。为此,请执行以下操作:If-Match
If-None-Match
-
确定需要锁定的实体并添加 version 属性。
HTML5 很好地支持属性,因此请将版本存储在 DOM 中(例如属性)。
data-*
data-etag
-
确定将从跟踪最新更新中受益的条目。在获取这些资源时,将值存储在 DOM 中(也许)。
Last-Modified
data-last-modified
-
在获取资源时,还要将 URI 嵌入到 DOM 节点(可能是 或 )中,以便轻松返回资源。
self
data-uri
data-self
-
调整 // 操作以使用并处理 HTTP 状态代码。
PUT
PATCH
DELETE
If-Match
412 Precondition Failed
-
调整操作以使用和处理 HTTP 状态代码。
GET
If-None-Match
If-Modified-Since
304 Not Modified
通过将元素和值嵌入到 DOM 中(或者可能是本机移动应用程序的其他位置)中,您可以通过不一遍又一遍地检索相同的内容来减少数据和电池电量的消耗。您还可以避免与其他客户端发生冲突,而是在需要协调差异时收到提醒。ETag
Last-Modified
以这种方式,只需对前端进行一些调整和一些实体级编辑,后端就可以提供时效性细节,您可以在构建客户友好型客户端时获利。