利用last-modify 和 If-Modified-Since 做页面缓存
2012-02-25 14:42
543 查看
在http中 Last-Modified 与
If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,
注意,在这 Last-Modified 是由服务器往客户端发送的HTTP 头,
另一个 If-Modified-Since是由客户端往服务器发送的头,
那么它们的到底是怎么玩的呢。。。。。用我项目中的一个实例来说明把!
(基金项目) 由于基金净值每天才更新一次,所以在项目启动的时候到数据库中拿一次数据,然后缓存这个list,同时也把缓存这个list的date保存起来,然后在通过定时器,定时在某个时间点去更新这个list,更新缓存date。
由于list每天才更新一次,那么前端页面输出这个list的数据也要一天才会变化一次,为了减缓服务器的压力,页面也能缓存起来。
个人理解原理:
可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的
Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面
是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面
是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。
在看看源码:
核心方法代码
/** * * @param lastModifiedTimestamp 缓存list的时间戳 * @return 是否大于缓存list的时间戳 */ public boolean checkNotModified(long lastModifiedTimestamp) { if (lastModifiedTimestamp >= 0 && !this.notModified && (this.response == null || !this.response.containsHeader(HEADER_LAST_MODIFIED))) { long ifModifiedSince = getRequest().getDateHeader(HEADER_IF_MODIFIED_SINCE);//取得客户端传上来的时间戳 if-modified this.notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000)); if (this.response != null) { if (this.notModified) {//大于 this.response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); //往响应流中状态设为305 } else { this.response.setDateHeader(HEADER_LAST_MODIFIED, lastModifiedTimestamp); //把最新的缓存时间戳赋给响应流中的 Last-Modified } } } return this.notModified; }
上面这个类在 org.springframework.web.context.request.ServletWebRequest
然后在controller中调用:
Java代码
@RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
public HashMap getFundNavInfoList(WebRequest webRequest,HttpServletRequest request,FundNavInput in) throws Exception {
//check is modify true代表客户端是最新的,直接返回,客户端根据响应流中304取本地缓存
if(webRequest.checkNotModified(lastModifyTime)){
return null;
}
//.........后面是代码不重要。。。。
总结:
这种方式适合数据更新频率慢,如果是实时数据,这种方式就不行了。。。。。。
欢迎大伙指出不足地方!。。。
原文链接:http://xw-qixia.iteye.com/blog/736963
If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,
注意,在这 Last-Modified 是由服务器往客户端发送的HTTP 头,
另一个 If-Modified-Since是由客户端往服务器发送的头,
那么它们的到底是怎么玩的呢。。。。。用我项目中的一个实例来说明把!
(基金项目) 由于基金净值每天才更新一次,所以在项目启动的时候到数据库中拿一次数据,然后缓存这个list,同时也把缓存这个list的date保存起来,然后在通过定时器,定时在某个时间点去更新这个list,更新缓存date。
由于list每天才更新一次,那么前端页面输出这个list的数据也要一天才会变化一次,为了减缓服务器的压力,页面也能缓存起来。
个人理解原理:
可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的
Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面
是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面
是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。
在看看源码:
核心方法代码
/** * * @param lastModifiedTimestamp 缓存list的时间戳 * @return 是否大于缓存list的时间戳 */ public boolean checkNotModified(long lastModifiedTimestamp) { if (lastModifiedTimestamp >= 0 && !this.notModified && (this.response == null || !this.response.containsHeader(HEADER_LAST_MODIFIED))) { long ifModifiedSince = getRequest().getDateHeader(HEADER_IF_MODIFIED_SINCE);//取得客户端传上来的时间戳 if-modified this.notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000)); if (this.response != null) { if (this.notModified) {//大于 this.response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); //往响应流中状态设为305 } else { this.response.setDateHeader(HEADER_LAST_MODIFIED, lastModifiedTimestamp); //把最新的缓存时间戳赋给响应流中的 Last-Modified } } } return this.notModified; }
/** * * @param lastModifiedTimestamp 缓存list的时间戳 * @return 是否大于缓存list的时间戳 */ public boolean checkNotModified(long lastModifiedTimestamp) { if (lastModifiedTimestamp >= 0 && !this.notModified && (this.response == null || !this.response.containsHeader(HEADER_LAST_MODIFIED))) { long ifModifiedSince = getRequest().getDateHeader(HEADER_IF_MODIFIED_SINCE);//取得客户端传上来的时间戳 if-modified this.notModified = (ifModifiedSince >= (lastModifiedTimestamp / 1000 * 1000)); if (this.response != null) { if (this.notModified) {//大于 this.response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); //往响应流中状态设为305 } else { this.response.setDateHeader(HEADER_LAST_MODIFIED, lastModifiedTimestamp); //把最新的缓存时间戳赋给响应流中的 Last-Modified } } } return this.notModified; }
上面这个类在 org.springframework.web.context.request.ServletWebRequest
然后在controller中调用:
Java代码
@RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })
public HashMap getFundNavInfoList(WebRequest webRequest,HttpServletRequest request,FundNavInput in) throws Exception {
//check is modify true代表客户端是最新的,直接返回,客户端根据响应流中304取本地缓存
if(webRequest.checkNotModified(lastModifyTime)){
return null;
}
//.........后面是代码不重要。。。。
@RequestMapping(method = { RequestMethod.GET, RequestMethod.POST }) public HashMap getFundNavInfoList(WebRequest webRequest,HttpServletRequest request,FundNavInput in) throws Exception { //check is modify true代表客户端是最新的,直接返回,客户端根据响应流中304取本地缓存 if(webRequest.checkNotModified(lastModifyTime)){ return null; } //.........后面是代码不重要。。。。 }
总结:
这种方式适合数据更新频率慢,如果是实时数据,这种方式就不行了。。。。。。
欢迎大伙指出不足地方!。。。
原文链接:http://xw-qixia.iteye.com/blog/736963
相关文章推荐
- 浏览器缓存分析之Last-Modified/If-Modified-Since
- 如何利用客户端缓存对网站进行优化? If-Modified-Since & If-None-Match
- Last-Modified、If-Modified-Since 实现缓存和 OutputCache 的区别
- 如何利用客户端缓存对网站进行优化? If-Modified-Since & If-None-Match
- 如何利用客户端缓存对网站进行优化? If-Modified-Since & If-None-Match
- http expires cache-control last-modified if-modified-since
- 有关Last-Modified 与 If-Modified-Since
- 图片缓存:浏览器刷新 和 304 Not Modified 与 If-Modified-Since 及 Cache-Control
- 图片缓存:浏览器刷新 和 304 Not Modified 与 If-Modified-Since 及 Cache-Control
- 有关Last-Modified 与 If-Modified-Since
- 有关Last-Modified 与 If-Modified-Since
- 通过Last-Modified,Etag利用客户端缓存对网站进行优化?
- Expires / Cache-Control / Last-Modified / If-Modified-Since / ETag / If-None-Match 区别使用
- If-Modified-Since页面是否更新
- 理解了一下HTTP头的Last-Modified 与If-Modified-Since
- If-Modified-Since页面是否更新
- 今天理解了一下HTTP头的Last-Modified 与If-Modified-Since
- HTTP的请求头 Last-Modified 与 If-Modified-Since 和 If-None-Match 与 ETags
- 有关Last-Modified 与 If-Modified-Since
- 让浏览器提高缓存效率,使用HTTP_IF_MODIFIED_SINCE缓存提高PHPWEB性能