java-Mongodb IsoDate和微服务上if-modified-since的问题
作者:互联网
当我使用spring数据在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);
除一个问题外,此方法运行完美:规范说标头if-modified-since具有以下格式:
If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
这意味着毫秒不会在if-modified-since标头上传递.但是,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);
标签:mongodb,microservices,java 来源: https://codeday.me/bug/20191026/1936718.html