在@RequestMapping请求方法体中设置 ETag
http://blog.didispace.com/books/spring-mvc-4-tutorial/publish/21-14/3-support-for-the-cache-control-etag-and-last-modified-response-header-in-controllers.html
参考资料
这里最重要的两个地方是:
1、调用 request.checkNotModified(lastModified) 方法
2、返回 null
方法调用在返回 true 之前会将响应状态码设为 304;
返回 null,在检查是否更改的方法调用返回 true 的基础上直接将方法返回,这会通知 Spring MVC 不再对请求做任何处理。
检查资源是否发生了更改有 3 种方式:
request.checkNotModified(lastModified) 方法会将传入的参数值(最后修改时间)与请求头'If-Modified-Since'的值进行比较
request.checkNotModified(eTag) 方法会将传入的参数值与请求头'ETag'的值进行比较
request.checkNotModified(eTag, lastModified) 方法会同时进行以上两种比较。也即是说,只有在两个比较都被判定为未修改时,服务器才会返回一个 304 响应状态码 HTTP 304 Not Modified(资源未修改)
lastModified:the last-modified timestamp in milliseconds
eTag:资源的唯一标示
总结:
最麻烦的问题在于,确定资源是否发生改变。可以用资源的最后修改时间(lastModified),资源的版本信息(etag),资源 MD5 取摘要信息(etag)等方式。我的项目目的是在浏览器段缓存后端接口的数据,麻烦的是,数据库一直在变化,无法确定最后修改时间,也没有版本信息。如果给返回的 json 数据做 MD5 摘要,也会先查询一遍数据库,失去了缓存的目的。最后发现该项目有操作日志模块,它记录各个模块的基本操作记录,有操作时间字段。从这里可以查询到数据的最后修改时间,最后就选择了这种折中的方式,解决了资源最后修改时间的问题。
弱 ETag 方式: Spring 以过滤器的形式对 ETags 提供透明支持,过滤器可以添加到 REST servlet 上。这个过滤器自动对响应生成一个 MD5 的哈希值使用
使用Spring Boot 项目的时候,可以通过添加配置类来添加过滤器:
ShallowEtagHeaderFilter过滤器会创建一个我们称为弱 ETag(与强 ETag 相对,后面会详述)的对象。过滤器会将渲染的 JSP 页面的内容(包括其他类型的内容)缓存起来,然后以此生成一个 MD5 哈希值,并把这个值作为 ETag 头的值写回响应中。下一次客户端再次请求这个同样的资源时,它会将这个 ETag 的值写到If-None-Match头中。过滤器会检测到这个请求头,然后再次把视图渲染出来并比较两个哈希值。如果比较的结果是相同的,那么服务器会返回一个304。正如你所见,视图仍然会被渲染,因此本质上这个过滤器并非节省任何计算资源。唯一节省的东西,是带宽,因为被渲染的响应不会被整个发送回客户端。
请注意,这个策略节省的是网络带宽,而非 CPU。因为对于每个请求,完整的响应仍然需要被整个计算出来。而其他在控制器层级实现的策略(上几节所述的)可以同时节省网络带宽及避免多余计算。
3.屏蔽HttpSecurity初始化的http header信息,屏蔽方式如下:
否则会出现:
Expires: 0
HTTP 1.0的遗留物,表示资源的过期时间, Expires 的值对应一个 GMT(格林尼治时间),比如Sat, 28 Apr 2018 09:40:01 GMT,表示2018年4月28日早上9:40:01以后,该资源会过期,需要重新请求服务器获取。
Pragma: no-cache
HTTP 1.0 的遗留物,当该字段值为no-cache的时候,客户端不会对资源缓存,每次都得向服务器发一次请求。
所以,如果不屏蔽的话,会无法缓存资源。
领取专属 10元无门槛券
私享最新 技术干货