Mongodb IsoDate和微服务上的if-modified-since问题

时间:2016-12-02 13:00:42

标签: java mongodb microservices

当我使用spring数据在MongoDB上插入文档时,我会执行以下操作:

Update update = new Update();
update.currentDate("lastModified");
mongoTemplate.upsert(query, update, MyDocument.class);

我正在使用MongoDB的currentDate,因为我想保存上次修改MyDocument的日期和我的MongoDB数据库所在的日期。

基于spec

  

If-Modified-Since请求标头字段与方法一起使用      使其成为条件:如果所请求的变体尚未修改      由于此字段中指定的时间,实体不会      从服务器返回;相反,304(未修改)响应将      在没有任何消息体的情况下返回。

因此,保存此日期的目的是根据收到的日期验证是否修改了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,1994年10月29日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。 000 Z),这意味着 我的数据库上的日期大于我的客户发送的日期:

2016-12-02T12:11:33.083Z> 2016-12-02T12:11:39.000Z

因为83毫秒。

最后一个问题是:解决这个问题的正确方法是什么,并且正如if-modified-since的规范所指出的那样正常工作?

1 个答案:

答案 0 :(得分:4)

您可以将比较前的最后修改日期millis设置为最大毫秒数这将在技术上否定毫秒偏移量。

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);