首页 > 代码库 > 开启 J2EE(六)— Servlet之Filter详解及乱码处理实例

开启 J2EE(六)— Servlet之Filter详解及乱码处理实例

定义和功能


Filter:过滤器,它能够在request到达Servlet之前预处理request,也可以在离开Servlet时处理response,通过对requestresponse的处理已达到过滤功能。但是Filter只是对requestresponse请求进行了拦截处理,通常不产生请求或者响应。

 

实现的接口


我们写Servlet需要继承一个类,Filter也一样,要实现一个接口(扩展性的体现啊):javax.servlet.Filter,并实现该接口的三个方法:

<span style="font-size:14px;">
init(FilterConfigfilterConfig)</span>

初始化方法,Servlet容器创建Servlet过滤器实例后将调用该方法。该方法将读取web.xml文件中Servlet过滤器的初始化参数。

<span style="font-size:14px;">
doFilter(ServletRequestrequest, ServletResponse response, FilterChain chain)</span>

doFilter完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时(详见下文),Servlet容器将先调用过滤器的doFilter方法。

FilterChain用于用户访问后续过滤器(链结构)

<span style="font-size:14px;">
destroy()</span>

释放Servlet过滤器占用的资源。

 

url配置


匹配Filter需要对哪些Servlet/JSP起作用,通过在web.xml配置文件中配置<url-pattern>,有如下方式:

1、精确匹配,对哪些Servlet起作用,不用任何修饰符

<span style="font-size:14px;">
<filter-mapping>  
  <filter-name>CharsetEncodingFilter</filter-name>  
  <url-pattern>/servlets/TestServlet</url-pattern>  
</filter-mapping></span>
2、扩展匹配,用*和扩展名组成

<span style="font-size:14px;">
<filter-mapping>  
  <filter-name>CharsetEncodingFilter</filter-name>  
  <url-pattern>*.jsp</url-pattern>  
</filter-mapping> </span>
3、路径匹配,包含一个目录和*

<span style="font-size:14px;">
<filter-mapping>  
  <filter-name>CharsetEncodingFilter</filter-name>  
  <url-pattern>/servlets/*</url-pattern>  
</filter-mapping> </span>
4、全部匹配,项目下所有的Servlet请求或相应

<span style="font-size:14px;">
<filter-mapping>  
  <filter-name>CharsetEncodingFilter</filter-name>  
  <url-pattern>/*</url-pattern>  
</filter-mapping>  </span>


具体流程

Filter是一种切入技术,并且可以在一个处理流程中切入多个Filter,通过多个Filter一层层过滤。

Filter属于声明式,也就是说只要在配置文件进行需要的配置,就会产生作用,并且会按照责任链模式一样,一层层过滤下去。



实例——采用Filter设置字符集处理乱码

  Filter一个很常用的功能,设置字符集,在通过request请求过程中往往那个会出现中文乱码现象,原因是Tomcat默认请求编码是ISO8859,简单的做法是这样:request.setCharacterEncoding("GB18030");但是对于大的项目,上百个上千个request,我们需要设置上百次上千次吗,肯定不会,那样修改起来无意是灾难,看我们通过Filter的实现:

  Filter实现类,继承自Filter接口

<span style="font-size:14px;">package com.zjj.drp.util.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * 采用Filter统一处理字符集
 * @author Jones
 *
 */
public class CharsetEncodingFilter implements Filter {
	//定义变量,用于存储从web.xml取出参数的值
	private String endcoding; 
	
	public void destroy() {

     }

	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		//进入Filter
		//System.out.println("CharsetEncodingFilter--->>>begin");
		//设置字符集,
		request.setCharacterEncoding(endcoding);
		
		//继续执行
 		chain.doFilter(request, response);
		//离开Filter
		//System.out.println("CharsetEncodingFilter--->>>end");
	}

	public void init(FilterConfig filterConfig) throws ServletException {
                //取得配置文件中参数encoding的值
		this.endcoding = filterConfig.getInitParameter("encoding");
		System.out.println("CharsetEncodingFilter.init()-->> endcoding=" + endcoding);
	}

}
</span>

配置web.xml

<pre name="code" class="html"><span style="font-size:14px;"><filter>
	<filter-name>CharsetEncodingFilter</filter-name>
	<filter-class>com.bjpowernode.drp.util.filter.CharsetEncodingFilter</filter-class>
	<init-param>
		<param-name>encoding</param-name>
		<param-value>GBK</param-value>
	</init-param>
</filter>

<filter-mapping>
	<filter-name>CharsetEncodingFilter</filter-name>
	<url-pattern>*.jsp</url-pattern>
</filter-mapping>
</span>

Filter批量设置(带*的),会影响一些效率,所以如果有效率瓶颈的Filter只设置需要的就行。


总结

  还需要注意的是Filter只对Post请求起作用,GET方式提交还是会出现乱码问题的。

  个人认为Filter最好的一点是,横切性,可插拔,使得系统变得更加灵活,我们只需要通过配置文件去配置这些Filter需要作用的地方就好。