http://www.jdon.com/40381

Last-Modified和Expires针对浏览器,而ETag则与客户端无关,所以可适合REST架构中。两者都应用在浏览器端的区别是:Expires日期到达前,浏览器不会再发出新的请求,除非用户按浏览器的刷新,所以,Last-Modified和Expires基本是降低浏览器向服务器发出请求的次数,而ETag更侧重客户端和服务器之间联系。

先谈Last-Modified和Expires,最新的Tomcat 7 将ExpireFilter
入其容器中,这样,Java
WEB也可以象Apache的Mod_expire模块一样对Http头部进行统一设置了,不过它只对响应文档类型进行统一设置判断,如
text/html或text/image
或/css等等,如果想对个别URL输出的jsp进行定制就不行,urlrewrite据说是可以,但是要把URL在其配置文件再配置一下,麻烦,一旦
jsp改动影响面大,还有一个问题就是web.xml配置了Tomcat
7容器的ExpireFilter,与容器耦合,移植性差(移植到Resin就不行了)。

所以,我在JiveJdon

4.2最新版本中,通过加入下面一段代码在服务器端对来自客户端的Last-Modified以及当前时间进行判断,如未过
期,response.setStatus设为304,可以终止后面的各种Jsp界面计算,直接返回浏览器一个304的响应包,JSP页面也不会输出到客
户端,将带宽节省给更加需要互动实时性的请求。

再谈谈ETag,ETag定义:RFC2616(也就是HTTP/1.1)中没有说明ETag该是什么格式的,只要确保用双引号括起来就行了,所以你可以用文件的hash,甚至是直接用Last-Modified,以下是服务器端返回的格式:
ETag: "50b1c1d4f775c61:df3" 客户端向服务端发出的请求:If-None-Match:
W/"50b1c1d4f775c61:df3"
这样,在J2EE/JavaEE服务器端,我们判断如果ETag没改变也是返回状态304,起到类似Last-Modified和Expires效果。

与Last-Modified和Expires区别是:如果过了Expires日期,服务器肯定会再次发出JSP完整响应;或者用户强按浏览器的刷新按
钮,服务器也必须响应,apache等静态页面输出也是这样,但是这时动态页面就发挥了作用,如果JSP涉及的业务领域模型还是没有更新,和原来一样,那
么就不必再将动态页面输出了(浏览器客户端已有一份),从Etag中获取上次设置的领域模型对象修改日期,和现在内存中领域模型(In-memory
Model)修改日期进行比较,如果修改日期一致,表示领域模型没有被更新过,那么返回响应包304,浏览器将继续用本地缓存的该页面,再次节省了带宽传输。

通过上述Expire和Etag两次缓存
可以大大降低服务器的响应负载,如果你的应用不是状态集中并发修改和实时输出,而是分散修改然后分发,如个人空间
个人博客(每个人只是修改它们自己的状态,不影响全局)或QQ类似个人工具,那么采取这样的方法效果非常明显,实际就是一种动态页面静态化技术,但比通常
事先进行页面静态化要灵活强大。

InfoQ的那篇:http://www.infoq.com/articles/etags还用MD5计算放入其中,Md5计算稍微复杂点,负载大了点,有的人结合Hibernate或数据库触发器来判断数据库数据是否更新,以决定Etag的更新,这将表现层和持久层耦合在一起,由于JiveJdon采取的是MDD/DDD模型驱动架构,表现层的Etag更新是根据中间业务层的模型对象修改日期来决定,不涉及数据库层,而且起到服务器缓存的更新和http的Etag更新一致的效果,在松耦合设计和性能上取得综合平衡。

代码如下:

             public static boolean checkHeaderCache(long adddays, long modelLastModifiedDate, HttpServletRequest request, HttpServletResponse response) {
// com.jdon.jivejdon.presentation.filter.ExpiresFilter
request.setAttribute("myExpire", adddays); // convert seconds to ms.
long adddaysM = adddays * 1000;
long header = request.getDateHeader("If-Modified-Since");
long now = System.currentTimeMillis();
if (header > 0 && adddaysM > 0) {
if (modelLastModifiedDate > header) {
// adddays = 0; // reset
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
if (header + adddaysM > now) {
// during the period happend modified
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return false;
}
} // if over expire data, see the Etags;
// ETags if ETags no any modified
String previousToken = request.getHeader("If-None-Match");
if (previousToken != null && previousToken.equals(Long.toString(modelLastModifiedDate))) {
// not modified
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return false;
}
// if th model has modified , setup the new modified date
response.setHeader("ETag", Long.toString(modelLastModifiedDate));
setRespHeaderCache(adddays, request, response);
return true; } public static boolean setRespHeaderCache(long adddays, HttpServletRequest request, HttpServletResponse response) {
request.setAttribute("myExpire", adddays); long adddaysM = adddays * 1000;
String maxAgeDirective = "max-age=" + adddays;
response.setHeader("Cache-Control", maxAgeDirective);
response.setStatus(HttpServletResponse.SC_OK);
response.addDateHeader("Last-Modified", System.currentTimeMillis());
response.addDateHeader("Expires", System.currentTimeMillis() + adddaysM);
return true;
}

HTTP 头缓存Last-Modified,ETag,Expires的更多相关文章

  1. 005-优化web请求一-gzip压缩、http缓存控制和缓存校验[Pragma、Expires、Cache-Control、max-age、Last-Modified、用户刷新访问、避免过度304]

    优化Web应用的典型技术:缓存控制头信息.Gzip.应用缓存.ETag.反应型技术[异步方法调用和WebSocket] 一.模板缓存 spring.thymeleaf.cache=true sprin ...

  2. Http请求头缓存设置方法

    1.直接在.aspx页面中设置最直接的,在.aspx页面中添加一行如下代码: <%@ OutputCache Duration="3600" VaryByParam=&quo ...

  3. 【转载】浏览器缓存详解:expires cache-control last-modified

    https://www.cnblogs.com/caiyanhu/p/6931624.html 下面的内容展示了一个常见的 Response Headers,这些 Headers 要求客户端最多缓存 ...

  4. http请求头缓存实现

    转自CSDN ouyang-web之路 原文链接:https://blog.csdn.net/cangqiong_xiamen/article/details/90405555 一.浏览器的缓存 st ...

  5. http强制缓存、协商缓存、指纹ETag详解

    目录 实操目录及步骤 缓存分类 强制缓存 对比缓存 指纹 Etag 摘要及加密算法 缓存总结 每个浏览器都有一个自己的缓存区,使用缓存区的数据有诸多好处,减少冗余的数据传输,节省网络传输.减少服务器负 ...

  6. HTTP响应头缓存控制

    在一般Web开发中,有时需要设置特殊的HTTP响应头阻止客户端(一般是浏览器)缓存(使用)该次请求的响应. 这时候大部分开发人员都是百度或谷歌几段代码复制粘贴即了事. 以下简述一下关于缓存控制的几种H ...

  7. node响应头缓存设置

    我把react项目分成4个板块,在路由的顶层 今天在手机上打开react项目的时候,发现平级路由跳转时某一个图片较多的板块图片总是渲染得很慢,这分明是重新发起请求了. 然后我先查一下react-rou ...

  8. 缓存&PWA实践

    缓存&PWA 实践 一.背景 从上一篇<前端动画实现与原理分析>,我们从 Performance 进行动画的性能分析,并根据 Performance 分析来优化动画.但,前端不仅仅 ...

  9. nginx-push-stream模块源码学习(三)——发布

    一.概述     发布:发布者将MSG post到某一特定通道上,channel将信息缓存 在说明发布流程之前有必要说明下channel和msg的数据结构. 二.数据结构 2.1 MSG     发布 ...

随机推荐

  1. Nginx -- nginx.conf 配置文件详讲

    Nginx服务器配置,nginx.conf文件代码详讲,结合不同楼主的博文得到: #关掉访问日志可以优化服务器 #定义Nginx运行的用户和用户组 #user nobody; #nginx进程数 #如 ...

  2. ACM -- 算法小结(八)字符串算法之Manacher算法

    字符串算法 -- Manacher算法 首先介绍基础入门知识,以下这部分来着一贴吧,由于是很久之前看的,最近才整理一下,发现没有保存链接,请原创楼主见谅. //首先:大家都知道什么叫回文串吧,这个算法 ...

  3. php uncode 转汉字编码

    $test = "%u4E0A%u6D77%u9EC4%u6D66";//$test = '\u5e86\u91cd\u5e86'; //庆重庆$temp = explode('% ...

  4. POJ 1286 Necklace of Beads(Polya简单应用)

    Necklace of Beads 大意:3种颜色的珠子,n个串在一起,旋转变换跟反转变换假设同样就算是同一种,问会有多少种不同的组合. 思路:正规学Polya的第一道题,在楠神的带领下,理解的还算挺 ...

  5. CMSIS-SVD Schema File Ver. 1.0

    <?xml version="1.0" encoding="UTF-8"?> <!-- date: 07.12.2011 Copyright ...

  6. Git 中文件的状态和流转区

    Git的文件主要处于三种状态,分别是 staged, modified, committed. Git文件流转有三个区域,分别是 工作区域. 索引区域. 本地数据区域. 要修改对一个文件进行操作,首先 ...

  7. wpf 分别用 xaml 和后台代码实现 色彩渐变

    xaml 方法: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.micros ...

  8. VS2010程序打包操作(超详细的)转

    1.  在vs2010 选择“新建项目”----“其他项目类型”----“Visual Studio Installerà“安装项目”: 命名为:Setup1 . 这是在VS2010中将有三个文件夹, ...

  9. 【QQ输入法】QQ输入法输入的英文字母顺便空格很大

    正常的输入出来是这个样子的: 现在变成了这个样子: 怎么解决这个问题呢: 快捷键 shift+空格   即可解决

  10. mongodb,redis,memcached,mysql对比

    1.性能都比较高,性能对我们来说应该都不是瓶颈总体来讲,TPS方面redis和memcache差不多,要大于mongodb 2.操作的便利性memcache数据结构单一redis丰富一些,数据操作方面 ...