每篇一句:任何普通人都可能随时被委以重任,任何显要人物也可能随时被取代。 ——《三体 III : 死神永生》
过滤器就是 Java 组件,请求发送到 servlet 之前,可以用过滤器截获和处理请求,在 servlet 结束之后,但在响应发回给客户之前,可以用过滤器处理响应
过滤器的作用
public class BeerRequestFilter implements Filter {
private FilterConfig fConfig;
//必须实现 init() ,通常只需保存配置对象
public void init(FilterConfig fConfig) throws ServletException {
this.fConfig = fConfig;
}
//doFilter() 中才做具体的工作
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String name = httpServletRequest.getRemoteUser();
if(name != null) {
fConfig.getServletContext().log("User" + name + "is updating");
}
//接下来调用的 过滤器 或 servlet
chain.doFilter(request, response);
}
public void destroy() {
//实现清理工作
}
}
每个过滤器都必须实现 Filter 接口中的三个方法:
1.init()
容器决定实例化一个过滤器时,在 init() 方法中完成调用过滤器之前的所有初始化任务
2.doFilter()
过滤器的功能在 doFilter() 方法中实现。doFilter() 方法有三个参数:
3.dostroy()
在真正撤销实例之前完成所需的所有清理工作
在实际考虑过滤器相互链接的过程时,可以想象成栈上的方法调用
声明过滤器
<filter>
<filter-name>BeerReuqestfilter-name>
<filter-class>com.example.web.BeerRequestFilterfilter-class>
param>
<param-name>LogFileNameparam-name>
<param-value>UserLog.txtparam-value>
param>
filter>
声明对应 URL 模式的过滤器映射
元素定义了哪些 Web 应用资源要使用这个过滤器
<filter-mapping>
<filter-name>BeerReuqestfilter-name>
<servlet-name>FilterServletservlet-name>
filter-mapping>
声明对应 Servlet 名的过滤器映射
元素定义了哪个 Web 应用资源要使用这个过滤器
<filter-mapping>
<filter-name>BeerReuqestfilter-name>
<servlet-name>FilterServletservlet-name>
filter-mapping>
当多个映射器映射到一个给定规则时,容器会使用一下规则:
<filter-mapping>
<filter-name>MonitorFilterfilter-name>
<url-pattern>*.dourl-pattern>
<dispatcher>REQUEST<dispatcher>
filter-mapping>
有四个值:
如果想创建定制请求或响应对象,只需要派生某个便利请求或响应 “包装器” 类。Sun 提供了 4 个便利类,以创建特定版本的请求或响应
包装器包装了实际的请求或响应对象,而且调用委托给实际的对象,还允许对定制请求或响应做所需的额外处理
压缩过滤器代码
public class CompressionFilter implements Filter {
private FilterConfig fConfig;
private ServletContext cServletContext;
public void init(FilterConfig fConfig) throws ServletException {
this.fConfig = fConfig;
cServletContext = fConfig.getServletContext();
cServletContext.log(fConfig.getFilterName() + " initailized.");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String valid_encodings = httpServletRequest.getHeader("Accept-Encoding");
if(valid_encodings.indexOf("gzip") > -1) {
CompressionResponseWrapper wrappedResp = new CompressionResponseWrapper(httpServletResponse);
wrappedResp.setHeader("Content-Encoding", "gzip");
chain.doFilter(request, wrappedResp);
GZIPOutputStream gzipServletOutputStream = wrappedResp.getGZIPOutputStream();
gzipServletOutputStream.finish();
cServletContext.log(fConfig.getFilterName() + ":finished the request");
}
else {
cServletContext.log(fConfig.getFilterName() + ": no encoding preformed.");
chain.doFilter(request, response);
}
}
public void destroy() {
fConfig = null;
cServletContext = null;
}
}
压缩包装器代码
public class CompressionResponseWrapper extends HttpServletResponseWrapper {
private GZIPServletOutputStream servletGzipOS = null;
private PrintWriter printWriter = null;
public CompressionResponseWrapper(HttpServletResponse response) {
super(response);
}
@Override
public void setContentLength(int length) { }
public GZIPOutputStream getGZIPOutputStream() {
return this.servletGzipOS.internalGzipOS;
}
private Object streamUsed = null;
@Override
public ServletOutputStream getOutputStream() throws IOException {
if((streamUsed != null) && (streamUsed != printWriter)) {
throw new IllegalStateException();
}
if( servletGzipOS == null) {
servletGzipOS = new GZIPServletOutputStream(getResponse().getOutputStream());
streamUsed = servletGzipOS;
}
return servletGzipOS;
}
@Override
public PrintWriter getWriter() throws IOException {
if( (streamUsed != null) && (streamUsed != servletGzipOS)) {
throw new IllegalStateException();
}
if(printWriter == null) {
servletGzipOS = new GZIPServletOutputStream(getResponse().getOutputStream());
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(servletGzipOS, getResponse().getCharacterEncoding());
printWriter = new PrintWriter(outputStreamWriter);
streamUsed = printWriter;
}
return printWriter;
}
}
辅助类代码
public class GZIPServletOutputStream extends ServletOutputStream {
GZIPOutputStream internalGzipOS;
public GZIPServletOutputStream(ServletOutputStream sos) throws IOException {
this.internalGzipOS = new GZIPOutputStream(sos);
}
public void write(int param) throws java.io.IOException {
internalGzipOS.write(param);
}
@Override
public boolean isReady() { return false; }
@Override
public void setWriteListener(WriteListener arg0) { }
}
如果有任何问题或建议,欢迎交流学习。