http协议-缓存控制:etag If-None-Match / Last-Modified If-Modified-Since
程序员文章站
2024-02-28 18:41:46
...
ETag和Last-Modified用法上的区别是:ETag必须由开发人员来使用,而Last-Modified服务器会自动判断。也就是说服务器自己能够获取文件的"Last-Modified"并和"If-Modify-Since"进行对比,进而决定发送什么样的响应。而ETag则必须由开发人员自己来和"If-None-Match"进行比较判断。
加上ETag一个用途是,假如文件被编辑了,但实际上内容并没有变化,此时可以指定ETag的值不变,这样它和浏览器发送过来的"If-None-Match"的值就相等了,进而可以指定响应为304,即未发生改变。如果不加ETag这个功能,则浏览器会发送200响应。
具体演示代码晚上再写,第一次研究技术熬到这么晚,困了。
请注意这个,有它没它差别很大:
如果不使用wrappedResponse而是原始的servletResponse,则在Ctrl+f5的情形下无论是ETag还是response设置都会消失,也就是说响应信息将不由本程序控制,而上述代码就可以解决这个问题。
ETagResponseWrapper,ETagResponseStream类代码见附件。
参考资料:[url=http://www.infoq.com/cn/articles/etags]infoq,etag[/url]
加上ETag一个用途是,假如文件被编辑了,但实际上内容并没有变化,此时可以指定ETag的值不变,这样它和浏览器发送过来的"If-None-Match"的值就相等了,进而可以指定响应为304,即未发生改变。如果不加ETag这个功能,则浏览器会发送200响应。
具体演示代码晚上再写,第一次研究技术熬到这么晚,困了。
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) req;
HttpServletResponse servletResponse = (HttpServletResponse) res;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ETagResponseWrapper wrappedResponse = new ETagResponseWrapper(servletResponse, baos);
chain.doFilter(servletRequest, wrappedResponse);
byte[] bytes = baos.toByteArray();
String token = '"' + EtagComputeUtils.getMd5Digest(bytes) + '"';
servletResponse.setHeader("ETag", token);
// servletResponse.setHeader("Cache-Control", "max-age=5"); //
servletResponse.setHeader("Cache-Control", "no-cache"); //
String previousToken = servletRequest.getHeader("If-None-Match");
if (previousToken != null && previousToken.equals(token)) {
logger.debug("ETag match: returning 304 Not Modified");
servletResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
} else {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MILLISECOND, 0);
Date lastModified = cal.getTime();
servletResponse.setDateHeader("Last-Modified", lastModified.getTime());
logger.debug("Writing body content");
servletResponse.setContentLength(bytes.length);
ServletOutputStream sos = servletResponse.getOutputStream();
sos.write(bytes);
sos.flush();
sos.close();
}
}
请注意这个,有它没它差别很大:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ETagResponseWrapper wrappedResponse = new ETagResponseWrapper(servletResponse, baos);
chain.doFilter(servletRequest, wrappedResponse);
如果不使用wrappedResponse而是原始的servletResponse,则在Ctrl+f5的情形下无论是ETag还是response设置都会消失,也就是说响应信息将不由本程序控制,而上述代码就可以解决这个问题。
ETagResponseWrapper,ETagResponseStream类代码见附件。
参考资料:[url=http://www.infoq.com/cn/articles/etags]infoq,etag[/url]
上一篇: 如何更好的使用Java8中方法引用详解
下一篇: 数据中心(kruskal)