当我使用 spring data 在 MongoDB 上插入文档时,我执行以下操作:
Update update = new Update();
update.currentDate("lastModified");
mongoTemplate.upsert(query, update, MyDocument.class);
我使用的是 MongoDB 的 currentDate,因为我想将 MyDocument 的上次修改日期与我的 MongoDB 数据库所在的日期一起保存。
基于spec :
The If-Modified-Since request-header field is used with a method to make it conditional: if the requested variant has not been modified since the time specified in this field, an entity will not be returned from the server; instead, a 304 (not modified) response will be returned without any message-body.
因此,保存此日期的目的是根据收到的日期验证 MyDocument 是否被修改。
因此,当我执行更新时,会在数据库上创建以下 IsoDate:
ISODate("2016-12-02T12:11:33.083Z")
因此,当客户想知道文档是否已更改时,他们会将此日期发回给我,然后我在数据库中查询:
Query query = new Query(where("id").is(filter.getId()));
Criteria criteria = Criteria.where("lastModified").gt(filter.getLastModified());
query.addCriteria(criteria);
return mongoTemplate.findOne(query, MyDocument.class);
除了一个问题之外,这一切都很完美:规范规定 header if-modified-since 具有以下格式:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
这意味着毫秒不会在 if-modified-since header 上传递。然而,MongoDB IsoDate 以毫秒为单位保存当前日期。因此,当两个日期完全相同时,查询不会返回 304 Not Modified,而是返回整个资源,因为查询将如下所示:
{ "id" : 123, "lastModified" : { "$gt" : { $java : 2016-12-02T12:11:39.000Z } } }
由于客户端没有发送毫秒,因此java将毫秒设置为零(2016-12-02T12:11:39.000Z),这意味着 我的数据库中的日期大于我的客户发送的日期:
2016-12-02T12:11:33.083Z > 2016-12-02T12:11:39.000Z
因为 83 毫秒。
最后一个问题是:解决这个问题的正确方法是什么,并且按照 if-modified-since 的规范建议正确工作?
最佳答案
您可以将上次修改日期毫秒设置为比较前的最大毫秒数,这从技术上讲会取消毫秒偏移。
public static Date setMaxMillis(Date day,Calendar cal) {
cal.setTime(day);
cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
return cal.getTime();
}
Query query = new Query(where("id").is(filter.getId()));
Criteria criteria = Criteria.where("lastModified").gt(setMaxMillis(filter.getLastModified(),Calendar.getInstance()));
query.addCriteria(criteria);
return mongoTemplate.findOne(query, MyDocument.class);
关于java - Mongodb IsoDate 以及微服务上 if-modified-since 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40932850/