对于最新的稳定版本,请使用 Spring Data REST 4.3.1Spring中文文档

对于最新的稳定版本,请使用 Spring Data REST 4.3.1Spring中文文档

本节介绍Spring Data REST如何使用标准HTTP标头来增强性能,条件化操作,并为更复杂的前端做出贡献。Spring中文文档

ETag、 和 标头If-MatchIf-None-Match

ETag 标头提供了一种标记资源的方法。这可以防止客户端相互覆盖,同时还可以减少不必要的调用。Spring中文文档

请看以下示例:Spring中文文档

例 1.具有版本号的 POJO
class Sample {

	@Version Long version; (1)

	Sample(Long version) {
		this.version = version;
	}
}
1 注解(如果您使用的是 Spring Data JPA,则为 JPA 注解,所有其他模块的注解为 Spring Data 注解)将此字段标记为版本标记。@Versionorg.springframework.data.annotation.Version

前面示例中的 POJO 在由 Spring Data REST 作为 REST 资源提供时,具有一个包含 version 字段值的标头。ETagSpring中文文档

我们可以有条件地、 或该资源,如果我们提供如下所示的标头:PUTPATCHDELETEIf-MatchSpring中文文档

curl -v -X PATCH -H 'If-Match: <value of previous ETag>' ...

仅当资源的当前状态与标头匹配时,才会执行操作。这种保护措施可以防止客户互相STOMP踏。两个不同的客户端可以获取资源,并且具有相同的 .如果一个客户端更新资源,它将在响应中获取新资源。但第一个客户端仍然具有旧标头。如果该客户端尝试使用标头进行更新,则更新将失败,因为它们不再匹配。相反,该客户端会收到要发送回的 HTTP 消息。然后,客户可以赶上,但这是必要的。ETagIf-MatchETagETagIf-Match412 Precondition FailedSpring中文文档

术语“版本”可能具有不同的语义,具有不同的数据存储,甚至在应用程序中具有不同的语义。Spring Data REST有效地委托给数据存储的元模型,以辨别字段是否已版本化,如果是,则仅在元素匹配时才允许列出的更新。ETag

If-None-Match 标头提供了一种替代方法。允许条件查询,而不是条件更新。请看以下示例:If-None-MatchSpring中文文档

curl -v -H 'If-None-Match: <value of previous etag>' ...

前面的命令(默认情况下)运行 .Spring Data REST 在执行 .如果标头与 ETag 匹配,则得出未发生任何更改的结论,并且不会发送资源的副本,而是发回 HTTP 状态代码。从语义上讲,它显示为“如果提供的标头值与服务器端版本不匹配,请发送整个资源。否则,不要发送任何东西。GETIf-None-MatchGET304 Not ModifiedSpring中文文档

此 POJO 来自基于 -的单元测试,因此它没有应用程序代码中预期的 (JPA) 或 (MongoDB) 注释。它只关注具有标题的字段如何产生结果。ETag@Entity@Document@VersionETag
1 注解(如果您使用的是 Spring Data JPA,则为 JPA 注解,所有其他模块的注解为 Spring Data 注解)将此字段标记为版本标记。@Versionorg.springframework.data.annotation.Version
术语“版本”可能具有不同的语义,具有不同的数据存储,甚至在应用程序中具有不同的语义。Spring Data REST有效地委托给数据存储的元模型,以辨别字段是否已版本化,如果是,则仅在元素匹配时才允许列出的更新。ETag
此 POJO 来自基于 -的单元测试,因此它没有应用程序代码中预期的 (JPA) 或 (MongoDB) 注释。它只关注具有标题的字段如何产生结果。ETag@Entity@Document@VersionETag

If-Modified-Since页眉

If-Modified-Since 标头提供了一种检查资源自上次请求以来是否已更新的方法,这使应用程序可以避免重新发送相同的数据。请看以下示例:Spring中文文档

例 2.域类型中捕获的上次修改日期
@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 日期/时间类型和 /)捕获此信息。@LastModifiedDateDateTimeDateCalendarlongLong

使用前面示例中的日期字段,Spring Data REST 返回类似于以下内容的标头:Last-ModifiedSpring中文文档

Last-Modified: Wed, 24 Jun 2015 20:28:15 GMT

可以捕获此值并将其用于后续查询,以避免在未更新时两次提取相同的数据,如以下示例所示:Spring中文文档

curl -H "If-Modified-Since: Wed, 24 Jun 2015 20:28:15 GMT" ...

使用上述命令,您要求仅当资源自指定时间以来发生更改时才提取资源。如果是这样,您将获得一个修订后的标头,用于更新客户端。否则,您将收到 HTTP 状态代码。Last-Modified304 Not ModifiedSpring中文文档

标头的格式完美,可以发回以供将来查询。Spring中文文档

不要将标头值与不同的查询混合和匹配。结果可能是灾难性的。仅当请求完全相同的 URI 和参数时,才使用标头值。
1 Spring Data Commons 的注解允许以多种格式(JodaTime 的、传统的 Java 和 JDK8 日期/时间类型和 /)捕获此信息。@LastModifiedDateDateTimeDateCalendarlongLong
不要将标头值与不同的查询混合和匹配。结果可能是灾难性的。仅当请求完全相同的 URI 和参数时,才使用标头值。

构建更高效的前端

ETag元素与 AND 标头相结合,可让您构建对消费者的数据计划和移动电池寿命更友好的前端。为此,请执行以下操作:If-MatchIf-None-MatchSpring中文文档

  1. 确定需要锁定的实体并添加版本属性。Spring中文文档

    HTML5 很好地支持属性,因此将版本存储在 DOM 中(例如属性之类的地方)。data-*data-etagSpring中文文档

  2. 确定将从跟踪最新更新中受益的条目。获取这些资源时,将值存储在 DOM 中( 也许)。Last-Modifieddata-last-modifiedSpring中文文档

  3. 获取资源时,还要在 DOM 节点中嵌入 URI(也许是 或),以便轻松返回资源。selfdata-uridata-selfSpring中文文档

  4. 调整 // 操作以使用和处理 HTTP 状态代码。PUTPATCHDELETEIf-Match412 Precondition FailedSpring中文文档

  5. 调整操作以使用和处理 HTTP 状态代码。GETIf-None-MatchIf-Modified-Since304 Not ModifiedSpring中文文档

通过在 DOM 中嵌入元素和值(或者本机移动应用程序的其他地方),您可以减少数据和电池电量的消耗,而无需一遍又一遍地检索相同的内容。您还可以避免与其他客户端发生冲突,而是在需要协调差异时收到警报。ETagLast-ModifiedSpring中文文档

以这种方式,只需对前端进行一些调整和一些实体级别的编辑,后端就可以提供时间敏感的细节,您可以在构建客户友好的客户端时从中获利。Spring中文文档