在Spring Data REST(通过Spring Boot 1.3.3)中,当GET
资源集合,例如people
时,@Version
属性不包含在资源中:
$curl -v http://localhost:8080/api/people/1
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /api/people/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.42.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< ETag: "0"
< Last-Modified: Tue, 26 Apr 2016 00:08:12 GMT
< Content-Type: application/hal+json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 26 Apr 2016 00:12:56 GMT
<
{
"id" : 1,
"createdDate" : {
"nano" : 351000000,
"epochSecond" : 1461629292
},
"lastModifiedDate" : {
"nano" : 351000000,
"epochSecond" : 1461629292
},
"firstName" : "Bilbo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "http://localhost:8080/api/people/1"
},
"person" : {
"href" : "http://localhost:8080/api/people/1"
}
}
* Connection #0 to host localhost left intact
默认情况下,或配置我的Spring Data存储库时:
@Configuration
public class ApplicationRepositoryConfiguration
extends RepositoryRestMvcConfiguration
{
@Override
protected void configureRepositoryRestConfiguration(
RepositoryRestConfiguration config
)
{
config.exposeIdsFor(Person.class);
config.setBasePath("/api/");
}
}
@Version
是数据行的版本,在更新时递增,并在查询特定资源时包含在ETag
HTTP标头数据中。我不想在集合中的每个资源上调用GET
,而是希望在集合@Version
中获取GET
,这样我就可以编写应用程序来检查@Version
1}}每个资源更新的值不执行 n
添加GET
往返。
有没有办法在集合@Version
的每个资源中包含GET
字段?
实体定义如下所示:
@Data @Entity @EntityListeners(AuditingEntityListener.class)
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@CreatedDate
@Column(nullable=false)
private Instant createdDate;
@LastModifiedDate
@Column(nullable=false)
private Instant lastModifiedDate;
@Version
@JsonProperty
private Long version;
…
}
答案 0 :(得分:16)
不,没有。 ETag是HTTP,等同于后端中表示为@Value
属性的HTTP。 Spring Data REST将所有在HTTP协议中具有相应机制的后端相关属性转换为:ids成为URI(也不应成为有效负载的一部分),@LastModifiedDate
属性成为标题,{{1} }属性,成为ETags。
原因很简单:如果您使用HTTP,请使用可用的协议方法来实现在数据访问级别上实现的内容。这是Spring Data REST 不的一个方面,只是简单地将数据库暴露给Web,但实际上检查了您的模型并将模型特征转换为协议特定的方法。
长话短说:使用Spring Data REST,您有两种更新选项:
@Version
没有PUT
标头 - 强制覆盖服务器上存在的任何内容,因为聚合被加载,传入的数据映射到它并且它被写回。如果另一个客户端在此期间更改了聚合(尽管这是一个非常短的窗口),您仍然可以应用乐观锁定。如果是这种情况,您会看到If-Match
。409 Conflict
标头的PUT
- Spring Data REST根据聚合的version属性的当前值检查提交的ETag,如果不匹配则返回If-Match
点。在这种情况下,客户端可以查找资源的当前状态并决定如何继续。他们可能只是在没有412 Precondition Failed
标题的情况下使用PUT
来覆盖服务器上的内容。可以对GET请求进行类似的优化:
If-Match
与GET
(ETag)/ If-None-Match
(带有Last-Modified标头值) - 如果资源仍在,则会看到If-Modified-Since
与以前相同的状态,因此您避免为响应花费带宽。304 Not Modified
将始终返回表示。答案 1 :(得分:0)
我认为在正文中不包含版本是错误的,因为我们经常拉一页资源,所以我们不能依赖ETag。至少它应该是可配置的,而目前还没有。
我只是向暴露版本的实体添加了另一个函数,我在 Spring Boot 2.4.4 上:
// ...
@Version
private Long version;
public Long getCurrentVersion() {
return version;
}
// ...