J2EE核心模式(第二版)中这样写道:使用拦截过滤器,作为一个可插拔式的过滤器,实现请求、响应的预处理和后处理。另有一个过滤器管理器,负责把各个处于松耦合关系的过滤器结合成一个链,并把控制依次委派给合适的过滤器。这样一来,不必改动现有代码就可能以各种方式加入、删除、合并这些过滤器。
可以说,上面这段话写得苦涩难懂,甚至容易给人误解,其实过滤器的作用就是你在载入一个页面(可能式jsp,或者servlet什么的)之前和之后,通过调用过滤器代码,来实现对现有代码的统一处理。下面我就用struts和struts里面经常出现的乱码问题对此进行详细的描述。
我们在采用struts框架的时候,经常会发生页面出现乱码的情况,这里有几种处理方法,比如说在每个页面的头部都进行处理,定义字符集;有些人深圳给每个需要显示的字符串进行一次转化,这些都需要对每个页面进行处理,工作量是非常大的,而且每个页面的处理方式基本都一样,在这种情况下,其实我们就可以使用过滤器了。
首先,我们需要在部署描述符文件中定义过滤器的相关参数(部署描述符文件可以是在不同的文件,很多系统都用web.xml),如下
例1:部署描述符文件-过滤器
<filter-mapping url-pattern='*.do' filter-name='PageFilter' />
<filter filter-name='PageFilter' filter-class='test.PageFilter' />
在上面这段语句中,定义了一个名为PageFilter的过滤器,它指向test.PageFilter.java这个类,当系统访问后缀名为.do的路径的时候(这里,.do是struts中常用的一种定义方法,一般是指向一个action类),就会调用这个过滤器了。
在这里,我们必须指定*.do所具体指向的内容
例2:部署描述符文件-*.do
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet>
上面这段话说明,页面指向的.do其实是指向一个叫action的servlet的,而具体的action代表什么,如下
例3:部署描述符文件-action的具体定义
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>validate</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
在这里,action指向了org.apache.struts.action.ActionServlet这个类,这是struts所默认指向的servlet类,其它参数不一一说明了。
下面,我们就要开始写过滤器的内容了。
例4:test.PageFilter.java
package test;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* 各页面的统一处理:设置页面的字符集。
* 有了此函数后相关页面就不需要再设置字符集等信息了。
*/
public class PageFilter extends HttpServlet implements Filter
{
private static final String CONTENT_TYPE = "text/html; charset=gb2312";
private static final String ENCODING = "gb2312";
private FilterConfig config = null;
/**
* 初始化。
*/
public void init(FilterConfig filterConfig)
{
this.config = filterConfig;
}
/**
* 执行过滤。
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
{
try
{
request.setCharacterEncoding(ENCODING);
response.setContentType(CONTENT_TYPE);
if (chain != null)
{
chain.doFilter(request,response);
}
}
catch (Exception e)
{
}
}
/**
* 返回过滤器配置信息。
*/
public FilterConfig getFilterConfig()
{
return this.config;
}
/**
* 设置过滤器配置信息。
*/
public void setFilterConfig(FilterConfig filterConfig)
{
this.config = filterConfig;
}
}
在上面这个类中,定义了一个名为doFilter的方法,当我们访问后缀名为do的路径的时候,系统就会自动先访问doFilter这里方法了,在这里,系统将页面的字符集定义为gb2312类型,这个,就不用在每个页面上面进行定义了。
上面是对过滤器使用的一些简单了应用,事实上,过滤器还可以定义多个,也可能存在其它很多方面的功能,这就需要大家一起研究探讨了。