- 浏览: 3506431 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
wanglf1207:
EJB的确是个不错的产品,只是因为用起来有点门槛,招来太多人吐 ...
weblogic-ejb-jar.xml的元素解析 -
qwfys200:
总结的不错。
Spring Web Flow 2.0 入门 -
u011577913:
u011577913 写道也能给我发一份翻译文档? 邮件437 ...
Hazelcast 参考文档-4 -
u011577913:
也能给我发一份翻译文档?
Hazelcast 参考文档-4 -
songzj001:
DbUnit入门实战
原文出处:http://blog.chenlb.com/2009/07/use-httpservletresponsewrapper-implement-etag-filter.html
最近对 http caching 感兴趣,决定一步步学习之。现先来了解 Etag。
什么是“ETag”?
HTTP协议规格说明定义ETag为“被请求变量的实体值” (参见 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html —— 章节 14.19)。 另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单 独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端。
如果http 请求头 If-None-Match 的内容,与服务器对资源算出来的 etag 相同,就返回 304 响应。
下面来动动手,实现一个 etag 过虑器。原理:用 HttpServletResponseWrapper 把正常的页面输出到一个 byte 数组里,然后计算 etag,etag 是否与请求头一致,再进一步处理。
代码实现:
- package com.chenlb.http;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.Calendar;
- import java.util.Date;
- import java.util.zip.CRC32;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpServletResponseWrapper;
- public class EtagFilter implements Filter {
- public void destroy() {}
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- HttpServletRequest servletRequest = (HttpServletRequest) request;
- HttpServletResponse servletResponse = (HttpServletResponse) response;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- HttpServletResponseWrapper hsrw = new MyHttpResponseWrapper(servletResponse, baos);
- chain.doFilter(request, hsrw);
- hsrw.flushBuffer();
- byte [] bytes = baos.toByteArray();
- CRC32 crc = new CRC32();
- crc.update(bytes);
- String token = "w/\"" + crc.getValue() + '"' ;
- servletResponse.setHeader("ETag" , token);
- // always store the ETag in the header
- String previousToken = servletRequest.getHeader("If-None-Match" );
- if (previousToken != null && previousToken.equals(token)) {
- // compare previous token with current one
- System.out.println("ETag match: returning 304 Not Modified" );
- servletResponse.sendError(HttpServletResponse.SC_NOT_MODIFIED);
- // use the same date we sent when we created the ETag the first time through
- servletResponse.setHeader("Last-Modified" , servletRequest.getHeader( "If-Modified-Since" ));
- } else {
- // first time through - set last modified time to now
- Calendar cal = Calendar.getInstance();
- cal.set(Calendar.MILLISECOND, 0 );
- Date lastModified = cal.getTime();
- servletResponse.setDateHeader("Last-Modified" , lastModified.getTime());
- System.out.println("Writing body content" );
- servletResponse.setContentLength(bytes.length);
- ServletOutputStream sos = servletResponse.getOutputStream();
- sos.write(bytes);
- sos.flush();
- sos.close();
- }
- }
- public void init(FilterConfig config) throws ServletException {}
- private static class MyHttpResponseWrapper extends HttpServletResponseWrapper {
- ByteServletOutputStream servletOutputStream;
- PrintWriter printWriter;
- public MyHttpResponseWrapper(HttpServletResponse response, ByteArrayOutputStream buffer) {
- super (response);
- servletOutputStream = new ByteServletOutputStream(buffer);
- }
- public ServletOutputStream getOutputStream() throws IOException {
- return servletOutputStream;
- }
- public PrintWriter getWriter() throws IOException {
- if (printWriter == null ) {
- printWriter = new PrintWriter(servletOutputStream);
- }
- return printWriter;
- }
- public void flushBuffer() throws IOException {
- servletOutputStream.flush();
- if (printWriter != null ) {
- printWriter.flush();
- }
- }
- }
- private static class ByteServletOutputStream extends ServletOutputStream {
- ByteArrayOutputStream baos;
- public ByteServletOutputStream(ByteArrayOutputStream baos) {
- super ();
- this .baos = baos;
- }
- public void write( int b) throws IOException {
- baos.write(b);
- }
- }
- }
web.xml 配置:
- < filter >
- < filter-name > etag </ filter-name >
- < filter-class > com.chenlb.http.EtagFilter </ filter-class >
- </ filter >
- < filter-mapping >
- < filter-name > etag </ filter-name >
- < url-pattern > *.jsp </ url-pattern >
- </ filter-mapping >
测试环境是 tomcat 6.0.18。
用 httpwatch 可以观察效果。
第二次请求(刷新),返回 304 。说明有效了。
过虑器同时还加了 Last-Modified 是为了兼容不支持 Etag 头的客户端。
infoq 下载来的代码没试用通过,原因是没有 flush PrintWriter。虽然有 304,但返回的内容为空。
当然算 etag 可用其它算法,我这里用 crc32。infoq 例子中用 md5。
发表评论
-
字符串分割--java中String.split()用法
2013-03-06 14:25 74154在java.lang包中有String.sp ... -
说明SOA监管(SOA Governance)实例(收录备查)
2012-12-19 11:35 1756SOA 已经不是单纯技术问 ... -
Injecting Spring Beans into Java Servlets
2012-11-01 10:21 1941If you are working in a Java ... -
Fitnesse使用
2012-05-05 13:27 23503Fitnesse 的使用 一,介绍 Fitnesse是一种 ... -
Customizing the new FitNesse parser
2012-05-05 13:13 2138FitNesse began its life using ... -
Eclipse Indigo - Cannot install Android ADT Plugin
2012-02-29 01:17 3888When I try to install the And ... -
Eclipse Indigo - Cannot install Android ADT Plugin
2012-02-29 01:13 1994When I try to install the And ... -
java application中内嵌ActiveX控件
2011-11-14 15:57 5527我这里用的是SWT/JFace开发application,SW ... -
Google Java Developer Tools Downloads
2011-08-09 00:04 2350WindowBuilder Pro原来叫WindowB ... -
Jalita
2011-08-06 00:49 1569Jalita (Java light terminal ada ... -
【转】用Java写字符终端界面
2011-07-29 13:13 2125终端界面GUI开源项目charva。 这个框架让你可以用开发 ... -
[转]mybatis下的分页,支持所有的数据库
2011-07-21 13:21 14843大 家都知道,mybatis的自带分页方法只是逻 ... -
Java framework for text- & console-based forms?
2011-07-21 01:06 1713charva jcurses JNA , ... -
JNA(Java Native Access)学习入门
2011-07-21 01:04 22655Java Native Access 项目 在 ... -
JAVA上加密算法的实现用例
2011-06-25 12:38 4886来源:www.ibm.com ... -
如何将GlassFish作为Windows服务运行
2011-05-18 23:21 2377本文档来自GlassFish官方网站,详细介绍了将 G ... -
JAVA UDP打洞必备知识点---NAT
2011-05-05 12:56 8709一、引言 RFCl631 ... -
Keystore概念,Keytool工具使用
2011-04-28 16:20 2909近来由于项目需要做Single Sign On, 研究了一 ... -
使用IntrospectorCleanupListener 解决quartz引起的内存泄漏
2011-04-20 11:59 13378"在服务器运行过程中,Spring不停的运行的计划任 ... -
利用Eclipse Profile Plugin监控分析Tomcat性能
2011-04-18 16:14 3707目前新版本的Eclipse在启动应用服务器的时候有一个新的选 ...
相关推荐
源代码 博文链接:https://msj.iteye.com/blog/179663
Servlet过滤器是Java Web开发中的一个重要组件,它允许在Servlet处理请求之前或之后对请求和响应进行拦截...通过合理的缓存策略和适当的配置,我们可以利用过滤器实现高效的数据缓存,降低服务器的负担,提高用户体验。
例如,可以使用`HttpServletRequestWrapper`和`HttpServletResponseWrapper`来实现这一功能。要改变某个方法的行为,通常需要继承这些包装类并重写相应的方法。 #### 总结 过滤器在Struts框架中扮演着关键角色,...
配置过滤器到web.xml文件中,指定URL模式或过滤器链,以便在合适的时候调用你的`ResponseWrapper`。这样,每次匹配的请求经过过滤器时,都会触发自定义的响应处理逻辑。 总结起来,Java过滤器提供了一种机制,让...
本教程将详细介绍如何通过实现一个过滤器(Filter)来解决JSP页面中的字符串乱码问题。 首先,我们需要理解字符编码的基础知识。字符编码是用来表示文本的一套规则,常见的有ASCII、GBK、UTF-8等。在Web应用中,...
总结起来,Java过滤器通过HttpServletResponseWrapper和自定义的输出流包装类,可以在HTTP响应被发送到客户端之前对其进行修改,这在需要动态调整响应内容、添加额外信息或者实现其他自定义逻辑的场景下非常有用。...
为了实现在过滤器中获取请求体内容以及响应内容的功能,本方案主要采用了以下技术手段: 1. **对`HttpServletRequest`进行封装**:通过创建`HttpServletRequestWrapper`子类来包装原始请求对象,并重写`getReader()...
4. **过滤器的使用**: - `cachedDo`方法是过滤器的核心,它在过滤器链中执行。首先,它获取当前请求的`CacheInfo`,如果存在且缓存过期,则创建`ProxyResponse`对象并继续过滤器链的执行。在过滤器链执行完成后,`...
Spring Security的保护机制主要是通过一系列过滤器实现的,这些过滤器组成一个过滤链。当请求到达时,过滤链会按照顺序处理,执行相应的安全逻辑。 #### 2.1 `DelegatingFilterProxy` 这是Spring Security与...
- 过滤器可以通过`HttpServletRequestWrapper`和`HttpServletResponseWrapper`来修改请求和响应的编码。 7. **服务器配置**: - 除了在过滤器中设置,还可以在Tomcat的`server.xml`中全局设置Connector的`...
3. 在 doFilter 中,new 自定义的 Request 和 Response 的类,并把它们分别传递到过滤器链中 4. 把该 Filter 配置到过滤器链的第一个位置上 Spring-Session 的源码分析 Spring-Session 的源码分析可以从以下几个...
1. **Filter Chain**: Spring Security 使用一系列过滤器来处理请求,如`HttpServletRequestWrapper` 和 `HttpServletResponseWrapper`,这些过滤器负责身份验证、授权和其他安全操作。 2. **Authentication ...
2. **Controller**:控制器是业务逻辑的入口点,通常用注解@Controller标记,负责处理请求并返回模型数据。 3. **Model**:模型对象,包含了业务数据。 4. **View**:视图负责展示模型数据。Spring MVC支持多种...
### JSP实现将动态网页转换成静态页面的方法 #### 概述 在Web开发中,为了提高网站的访问速度及减少服务器对数据库的频繁访问,一种常见的做法是将原本动态生成的内容转换为静态页面。本篇文章将深入探讨如何通过...
1. **Servlet API**:在 Java Web 开发中,`HttpServletRequestWrapper` 和 `HttpServletResponseWrapper` 就是典型的装饰器模式应用,它们允许开发者在原始请求和响应对象的基础上添加额外的功能,如日志记录、安全...
通过实现`Filter`接口,重写`doFilter()`方法,设置请求和响应的编码,如`HttpServletRequestWrapper`和`HttpServletResponseWrapper`。 8. 字符集理解: 对于不同的字符集,如GBK、UTF-8、GB2312等,理解它们之间...
这个过滤器应该实现`Filter`接口,并在`doFilter`方法中调用`HttpServletRequestWrapper`和`ServletResponseWrapper`,以便Spring Security可以检查请求的合法性。 ```java public class SpringSecurityCxfFilter ...
- **配置Filter**:在web.xml中配置过滤器,指定需要拦截的URL模式。 - **处理乱码**:在`doFilter`方法中,对请求和响应进行编码设置。 ```java chain.doFilter(request, new HttpServletResponseWrapper...