上一篇说了下servlet,不知道对各位有没有什么帮助,现在说下filter吧。
Filter也是servlet包下的一个接口,中文意思是“过滤器”,其他语言也能时常看到这个单词,它的主要作用就是过滤,对!过滤你想过滤的东西,例如:文件,http请求地址,字符编码等等(在actionScript中filter极易编写,功能也非常强大)。
Api地址:http://docs.oracle.com/javaee/5/api/
下面是api中对于filter的介绍
从这个介绍可以看出filter是从servlet2.3版本才加入的,用来执行过滤任务的组件,这里值得注意的是filter并不是一个servlet,它会在servlet执行前执行以起到过滤作用。
Api中还列举了下面这些可以过滤的例子,当然不仅仅局限于这些:
下面分析下filter相关的接口。
Filter接口:filter是servlet包中的一个接口,它其中只有三个方法,doFilter方法最重要,在这个方法里写你的关键代码。
/** * 初始化方法 */ public void init(FilterConfig filterConfig) throws ServletException { } /** * 过滤执行方法,你的代码放在这个方法中 */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { } /** * 默认销毁方法 */ public void destroy() { }
FilterChain 接口:中文意思是过滤器调用链,FilterChain 只有一个方法,通过chain. doFilter会调用下一个filter。
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { }
FilterConfig接口:这是filter的相关参数配置接口,可以通过这个接口获取到filter的相关信息,在此就不介绍了。
现在就分析下filter的工作原理和流程:
要弄清filter和servlet的调用流程不如自己建立一个工程,打印些日志就非常明了了。
1.首先建立一个web工程filter_test,然后建立一个servlet起名为TestServlet。
<!-- servlet 配置 --> <servlet> <description>test servlet</description> <display-name>test servlet</display-name> <servlet-name>testServlet</servlet-name> <servlet-class>TestServlet</servlet-class> </servlet> <!-- servlet请求映射配置 --> <servlet-mapping> <servlet-name>testServlet</servlet-name> <url-pattern>/servlet/testServlet</url-pattern> </servlet-mapping>
TestServlet的实现:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 类描述:测试servlet * @author ming.li<br/> * <a href="http://g21121.iteye.com">iteye bolg</a> * @time 2012-2-2 下午04:10:46 */ public class TestServlet extends HttpServlet { /** * 默认构造方法 */ public TestServlet() { System.out.println("TestServlet:构造方法"); } /** * 默认初始化方法 */ public void init() throws ServletException { System.out.println("TestServlet:初始化方法"); } /** * 默认get请求处理方法 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("TestServlet:get请求处理方法"); response.sendRedirect("http://www.baidu.com/"); } /** * 默认post请求处理方法 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("TestServlet:post请求处理方法"); } /** * 默认销毁方法 */ public void destroy() { System.out.println("TestServlet:销毁方法"); } }
2.然后创建第一个filter。
Filter在web.xml中的配置:
<!-- 第一个filter --> <filter> <description>test fileter for TestServlet 1</description> <filter-class>TestFilter</filter-class> <filter-name>testFilter</filter-name> </filter> <!-- filter映射配置 --> <filter-mapping> <filter-name>testFilter</filter-name> <servlet-name>testServlet</servlet-name> <url-pattern>/servlet/</url-pattern> <!-- dispatcher是servlet2.4才加入的的,这点需要注意一下 --> </filter-mapping>
•在<filter-mapping>配置中,<servlet-name>标签中填写的就是我们要处理的servlet,也就是testServlet,注意这里填写的是servlet-name而不是类名称。
•<url-pattern>标签中填写的就是拦截的请求链接,即在该请求下才调用filter。
•<dispatcher>是在servlet2.4才加入的,里面有
实现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 ming.li<br/> * <a href="http://g21121.iteye.com">iteye bolg</a> * @time 2012-2-2 下午04:21:29 */ public class TestFilter implements Filter { /** * 默认初始化方法 */ public void init(FilterConfig fc) throws ServletException { System.out.println("TestFilter:初始化方法"); } /** * 默认处理方法 */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("TestFilter:处理方法,doFilter之前"); chain.doFilter(request, response); System.out.println("TestFilter:处理方法,doFilter之后"); } /** * 默认销毁方法 */ public void destroy() { System.out.println("TestFilter:销毁方法"); } }
3.运行项目。
运行过程中我们发现控制台打印了这一句话:TestFilter:初始化方法
说明filter的初始化在启动服务器的时候已经完成了。
然后我们打开浏览器在地址栏里敲入地址:http://localhost:8080/filter_test/servlet/testServlet
控制台打印的信息是:
从这个信息打印的顺序我们可以大致分析出filter和servlet的工作流程。
1).servlet的构造方法
2). servlet的初始化方法
3). filter的doFilter方法, chain.doFilter之前的内容
4). servlet对应的请求方法(get post delete put)
5). filter的doFilter方法, chain.doFilter之后的内容
4.此时我再添加一个filter,这个filter同样会处理servlet,看看这两个filter之间有什么联系。
命名另一个filter为OtherTestFilter,web.xml配置为:
<!-- 第二个filter --> <filter> <description>test fileter for TestServlet 2</description> <filter-class>OtherTestFilter</filter-class> <filter-name>otherTestFilter</filter-name> </filter> <!-- filter映射配置 --> <filter-mapping> <filter-name>otherTestFilter</filter-name> <servlet-name>testServlet</servlet-name> <url-pattern>/servlet/</url-pattern> </filter-mapping>
OtherTestFilter实现为:
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 ming.li<br/> * <a href="http://g21121.iteye.com">iteye bolg</a> * @time 2012-2-3 上午10:07:21 */ public class OtherTestFilter implements Filter { /** * 默认初始化方法 */ public void init(FilterConfig fc) throws ServletException { System.out.println("OtherTestFilter:初始化方法"); } /** * 默认处理方法 */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("OtherTestFilter:处理方法,doFilter之前"); chain.doFilter(request, response); System.out.println("OtherTestFilter:处理方法,doFilter之后"); } /** * 默认销毁方法 */ public void destroy() { System.out.println("OtherTestFilter:销毁方法"); } }
5.我们依旧打开http://localhost:8080/filter_test/servlet/testServlet
这个地址,看控制台打印日志是什么:
结合前面的分析,我们发现如果有多个filter处理同一个servlet的时候,他们的执行顺序如下图
所以经过上面的分析我们不难看出,FilterChain的作用就是以数组形式储存储存要调用的filters,然后在filter中调用chain.doFilter(),执行列表中下一个filter中doFilter()之前代码,以此类推,是不是已经晕了,呵呵。
了解了filter的工作原理和工作流程,我们就能更简单的开发对应的filter了,具体例子,大家可以搜索一下,网上有很多。