HTTP 缓存

      项目中有一个公共页面mian.jsp,里面有大量的javascript代码,需要将他分离出来,尽可能的利用浏览器的缓存。一些常规的java脚本只需要放到js文件中就行,还有一些javascript代码是动态的(也就是说会有一些jstl标签代码)就不能放到js文件中了。我采取的方案是将这些含有jstl标签的javascript脚本代码放入到一个gsp文件中,然后在页面中引用。例如:

<script type="text/javascript" src="${staticurl}/js/userAutoTips.jsp"></script>

   显然这种方式仅仅是实现了javascript脚本的分离,这种页面默认是不缓存的,所以每次需要的时候仍然会请求信息。要想让服务器缓存这些页面,需要做点手脚。

      首先我们来看一下Http的缓存。

HTTP缓存 / Http Cache

1、ETag
Http1.1中没有规定ETag的格式和生成方式,只要求用双引号括起来。因此可以用MD5,或者直接用文件的最后修改时间。Tomcat就采用 文件大小 + "-" + 文件最后修改时间的毫秒数 来生成ETag。
Etag 与 If-None-Match 对应。
第一次请求时,服务端响应头中有ETag(红色下划线 所示)。


HTTP 缓存_第1张图片
 

第二次请求时,请求头中就带有If-None-Match(红色下划线 所示)。服务器判断请求头中 If-None-Match 与服务端计算的ETag是否一致,如果一致就表示没有更新,返回304,否则按第一次请求时处理。

HTTP 缓存_第2张图片


2、Last-Modified
Last-Modified与If-Modified-Since对应。
第一次请求时,响应头中带有 Last-Modified(蓝色下划线 所示),格式如:Wed, 22 Jul 2009 07:08:07 GMT,是零时区的 GMT 时间。


 
  HTTP 缓存_第3张图片

第二次请求时,请求头中就带有If-Modified-Since(蓝色下划线 所示)。服务器判断请求头中If-Modified-Since与请求资源的最后修改时间是否一致,如果一致就表示资源没有更新,返回304,否则按第一次请求时处理。


 
  HTTP 缓存_第4张图片


3、Cache-Control
Cache-Control是一个集合属性,可以包含多个子属性。

  • max-age - 以秒为单位的超时,覆盖Expires属性。
  • public - 允许保存在共享缓存中。
  • private - 只允许保存在私有缓存中。
  • no-cache - 不允许缓存。
  • no-store - 不允许缓存在持久介质中。
  • no-transform - 不允许转换存储系统。

第一次请求时,响应头中带有Cache-Control(红色下划线 所示)。


 
 

HTTP 缓存_第5张图片

第二次请求时,浏览器判断Cache-Control,如果是max-age并且其值有效(在有效的缓存时间内),浏览器直接使用本地缓存,不向服务端发送请求,否则按第一次请求处理;如果是no-cache和no-store,不缓存,每次都是重新向服务端请求。


  HTTP 缓存_第6张图片
 
说明:
在firebug中,使用本地缓存时,资源名称会变成 灰色


4、Expires
第一次请求时,响应头中带有 Expires(蓝色下划线 所示),格式如:Wed, 22 Jul 2009 07:08:07 GMT,是零时区的 GMT 时间。


  HTTP 缓存_第7张图片
 


第二次请求时,浏览器判断Expires,如果Expires是有效的,浏览器直接使用本地缓存,不向服务端发送请求,否则按第一次请求处理。


 
 
HTTP 缓存_第8张图片
 

 

说明: 在firebug中,使用本地缓存时,资源名称会变成灰色

 

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缓存 服务器端缓存 这些技术综合在一起,可以大大增强每台服务器抗高负载能力,把带宽留给更需要实时更新的模型或页面。


这 种方式比静态化页面的好处是:精确性,静态页面.html比如Apache中mod_expire设置,如设置expire为十分钟,如果过了十分钟,其 实页面内容还是没有变,也要加载静态页面到客户端,而结合Etag的动态页面,不但起到静态页面一样的效果(其实经过Apache处理的静态页面html 也是动态页面),而且可以做到精确制导,就象多国部队轰炸利比亚一样,精确打击。这是灵活性的魅力。

 


5、附录
1、Cache-Control和Expires对F5和Ctrl+F5无效。当按F5刷新或按Ctrl+F5强制刷新时,IE和Firefox都会忽视本地缓存,重新向服务端发起请求

Firefox IE
刷新 F5
Cache-Control: max-age=0
强制刷新 Ctrl+F5
Pragma: no-cache
Cache-Control: no-cache
刷新 F5
If-Modified-Since: Sun, 21 Nov 2004 14:35:21 GMT
If-None-Match: "14f598-916-a64a7c40"
强制刷新 Ctrl+F5
Cache-Control: no-cache

你可能感兴趣的:(java,html,cache,缓存)