缓存Filter工作流程:
1)截获浏览器提交的request
2)如果请求方式为"POST"则不经过缓存
3)若请求方式为"GET"且存在缓存且缓存没有过期,返回缓存数据
4)若不存在缓存或缓存已过期,则查询并创建缓存;返回数据
使用缓存Filter注意事项
1)缓存Filter不用于实时变化数据。适用于数据变化不大但访问次数多的内容:如论坛、博客、新闻等
2)缓存Filter不用于"POST"方式提交数据,如登陆、发表文章等
3)缓存内容要依赖于Cookie而不能依赖于Session,即用Cookie而不是Session纪录客户身份。且无论客户身份是管理员还是普通浏览着 Servlet 输出数据都相同,只能在浏览器层使用JavaScript根据Cookie来决定显示什么内容。
参照《java Web整合开发...》实现一个简单的缓存Filter主要完成以下工作
1)继承 HttpServletResponseWrapper ,重写必要方法
package servlet.filter;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class CacheResponseWrapper extends HttpServletResponseWrapper {
/*可用作 Writer 的字符缓冲区。当数据写入流时,缓冲区自动扩大*/
private CharArrayWriter cacheWriter = new CharArrayWriter();
public CacheResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public void flushBuffer() throws IOException {
cacheWriter.flush();
}
@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(cacheWriter);//返回缓存内容的Writer;
}
public void finishResponse(){
cacheWriter.close();
}
/*Getters and Setters*/
public CharArrayWriter getCacheWriter() {
return cacheWriter;
}
public void setCacheWriter(CharArrayWriter cacheWriter) {
this.cacheWriter = cacheWriter;
}
}
2)Filte接口
package servlet.filter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.URLEncoder;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CacheFilter implements Filter{
/**/
private ServletContext context;
/**/
private File tempDir;
private long cacheTime = Long.MAX_VALUE;
/*撤销*/
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest) request;
HttpServletResponse rep=(HttpServletResponse) response;
/*请求方式为POST则不经过缓存*/
if("POST".equalsIgnoreCase(req.getMethod())){
chain.doFilter(req, rep);
}
String uri=req.getRequestURI();
if(uri==null){
uri="";
}
/*替换特殊字符*/
uri=uri.replace(req.getContextPath()+"/", "");
uri=uri.trim().length()==0 ? "index.jsp" : "";
uri=req.getQueryString()==null ? uri : uri+req.getQueryString();
/*缓存文件*/
File cacheFile=new File(tempDir,URLEncoder.encode(uri,"UTF-8") );
/*缓存文件不存在或已过期,则请求Servlet并缓存数据*/
if( !cacheFile.exists()
|| ( cacheFile.length()==0 )
|| ( System.currentTimeMillis()-cacheFile.lastModified() )>cacheTime ){
/*使用自定义response 缓存输出内容*/
CacheResponseWrapper crep = new CacheResponseWrapper(rep);
chain.doFilter(req, crep);
/*创建缓存文件*/
tempDir.mkdir();
cacheFile.createNewFile();
/*输出内容到缓存文件*/
char[] content=crep.getCacheWriter().toCharArray();
Writer writer=new OutputStreamWriter( new FileOutputStream(cacheFile));
writer.write(content);
writer.flush();
writer.close();
}
String contenType=context.getMimeType(req.getRequestURI());
rep.setContentType(contenType);
/*读取缓存文件内容,输出到浏览器*/
Reader ins = new InputStreamReader( new FileInputStream(cacheFile),"UTF-8" );
int len;
char[] cbuf=new char[1024];
StringBuilder sb=new StringBuilder();
while( (len=ins.read(cbuf) )>-1 ){
sb.append(cbuf, 0, len);
}
ins.close();
rep.getWriter().write(sb.toString());
}
/*初始化*/
public void init(FilterConfig config) throws ServletException {
context=config.getServletContext();
/*从配置文件获取*/
tempDir=new File(config.getInitParameter("cacheDir"));
/*从配置文件获取缓存时间*/
cacheTime=Long.parseLong(config.getInitParameter("cacheTime"));
}
}
3)配置
<filter>
<filter-name>cacheFilter</filter-name>
<filter-class>servlet.filter.CacheFilter</filter-class>
<init-param>
<param-name>cacheDir</param-name>
<param-value>cache</param-value>
</init-param>
<init-param>
<param-name>cacheTime</param-name>
<param-value>100000</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>cacheFilter</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
本文详细介绍了缓存Filter在J2EE中的工作流程,包括拦截GET请求、检查缓存、处理POST请求等情况。同时,强调了使用缓存Filter的注意事项,如不适用于实时数据和POST提交,以及依赖Cookie而非Session。通过《java Web整合开发...》一书,实现了一个简单的缓存Filter,该Filter重写了HttpServletResponseWrapper的相关方法。
684

被折叠的 条评论
为什么被折叠?



