码迷,mamicode.com
首页 > 其他好文 > 详细

过滤器

时间:2015-05-16 09:09:27      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:web应用

1. 过滤器

1.1. 过滤器

1.1.1. 什么是过滤器

过滤器是Servlet2.3规范之中一种特殊的Web组件,可以作为Servlet的辅助性插件存在。例如,对信息的筛选是很多Servlet里面的一个必须的前提,但是相同的功能在每个Servlet中都编写不仅仅不利于以后修改过滤逻辑,也不利于功能的重用,这时可以将这一部分非决定性的功能放在一个过滤器中,通过配置由容器控制所有请求在到达真正的处理逻辑Servlet之前先通过过滤器的检查。如果过滤逻辑需要修改,那么只需要修改这一个组件即可。所以这种可随时添加、修改,作为Servlet补充功能的Web组件是非常必要的。

1.1.2. 如何编写过滤器

编写过滤器遵循下列步骤:

  1. 编写一个实现了Filter接口的类
  2. 实现Filter接口的三个方法,过滤逻辑在doFilter方法中实现
  3. 在Web程序中注册过滤器
  4. 把过滤器和Web应用一起打包部署

步骤一、实现Filter接口

Filter是过滤器API中最核心的接口,定义一个Java类实现该接口以提供过滤逻辑。代码如下:

    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;

    public class CommentFilter implements Filter{
        //… …
    }

步骤二、实现doFilter方法

Filter接口中共定义了三个方法,分别是init,doFilter,destroy方法。init方法在创建Filter时会被调用,且只调用一次,一般在该方法中做一些数据的准备工作,可以通过传入的FilterConfig参数获取在web.xml文件中配置提供给过滤器的初始参数。destroy方法只有在销毁过滤器对象时被调用一次,用于释放一些资源的操作。doFilter方法内编写过滤器的具体处理逻辑,会被多次执行。该方法共有三个参数,请求和响应用于获取数据以及追加数据,FilterChain是过滤器链,负责多过滤器的传递。

实现代码如下:

  1. import java.io.IOException;
  2. import java.io.PrintWriter;
  3. import javax.servlet.*;
  4. import javax.servlet.http.*;
  5. public class CommentFilter implements Filter{
  6.         private FilterConfig config;
  7.     
  8.         public void destroy() {
  9.             System.out.println("CommentFilter1‘s destroy...");
  10.         }
  11.         /*
  12.          * 容器会调用doFilter方法来处理请求(
  13.           * 相当于servlet的service方法)。
  14.          * 容器会将request对象(arg0)和response对象
  15.          * (arg1)作为参数传给doFilter方法。
  16.           */
  17.         public void doFilter(ServletRequest arg0,
  18.                              ServletResponse arg1, FilterChain arg2)
  19.                              throws IOException, ServletException {
  20.                 HttpServletRequest request = (HttpServletRequest)arg0;
  21.                 HttpServletResponse response =(HttpServletResponse)arg1;
  22.                 request.setCharacterEncoding("utf-8");
  23.                 response.setContentType("text/html;charset=utf-8");
  24.                 PrintWriter out = response.getWriter();
  25.                 String content = request.getParameter("content");
  26.                 if(content.indexOf(illegalStr) != -1){
  27.                     //有敏感字
  28.                     out.println("<h1>评论内容包含了敏感字</h1>");
  29.                 }else{
  30.                     //没有敏感字
  31.                     // 执行FilterChain的doFilter会调用后续的过滤器或者servlet。
  32.                     arg2.doFilter(arg0, arg1);
  33.                 }
  34.                 System.out.println("Filter1‘s doFilter end.");
  35.         }
  36.     
  37.         /*
  38.          * FilterConfig对象可以用来访问过滤器的初始化参数。
  39.          * init方法只会执行一次。
  40.          */
  41.         public void init(FilterConfig arg0) throws ServletException {
  42.             System.out.println("CommentFilter1‘s init...");
  43.             config = arg0;
  44.         }
  45. }

步骤三、注册过滤器

在web.xml文件中注册过滤器,代码如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.4"
  3.     xmlns="http://java.sun.com/xml/ns/j2ee"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  6.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  7. <!-- 过滤器 -->
  8. <filter>
  9.     <filter-name>filter1</filter-name>
  10.     <filter-class>web.CommentFilter</filter-class>
  11.     <init-param>
  12.         <param-name>illegalStr</param-name>
  13.         <param-value>胡萝卜</param-value>
  14.     </init-param>
  15. </filter>
  16. <filter-mapping>
  17.     <filter-name>filter1</filter-name>
  18.     <url-pattern>/comment</url-pattern>
  19. </filter-mapping>
  20. </web-app>

步骤四、部署过滤器

将编译后的过滤器和其他Web组件类合在一起,连同web.xml文件放进应用程序结构中即可。

1.1.3. 过滤器的执行流程

技术分享

图 – 1

如图-1所示为过滤器的执行流程。客户端发来请求后,不会直接将请求送达Servlet,而是先走过滤器1的doFilter方法中的code1,当遇到chain.doFilter()方法时,控制权交到service()方法,执行业务逻辑,但执行结束后并不会立即将响应返回给客户端,而是回到过滤器1的doFilter()方法中code2部分,如果该部分有代码就会执行,执行结束后才会将response对象返回给客户端。

从流程中可以看到,过滤器不仅仅对Servlet的执行前起到过滤作用,对于执行后同样有过滤效果。所以,过滤器是对request和response的检查。

1.1.4. 过滤器的优先级

在一个Web应用中,可以有多个过滤器,它们的优先级由位于web.xml文件中的声明顺序决定,具体是按照<filter-mapping>的顺序来决定的。如下代码所示,filter1和filter2都已经注册,执行顺序是filter2 ( filter1 。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.4"
  3.     xmlns="http://java.sun.com/xml/ns/j2ee"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  6.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  7. <!-- 过滤器 -->
  8. <filter>
  9.     <filter-name>filter1</filter-name>
  10.     <filter-class></filter-class>
  11. </filter>
  12. <filter>
  13.     <filter-name>filter2</filter-name>
  14.     <filter-class></filter-class>
  15. </filter>
  16. <filter-mapping>
  17.     <filter-name>filter2</filter-name>
  18.     <url-pattern>/comment2</url-pattern>
  19. </filter-mapping>
  20. <filter-mapping>
  21.     <filter-name>filter1</filter-name>
  22.     <url-pattern>/comment1</url-pattern>
  23. </filter-mapping>
  24. </web-app>

1.1.5. 多个过滤器的执行流程

技术分享

图 – 2

如图-2所示,为多个过滤器的执行流程,过滤器1的doFilter的code1 ( 过滤器2的doFilter的code1 ( service()方法 ( 过滤器2的doFilter的code2 ( 过滤器1的doFilter的code2 ( 返回给客户端

在这个动作的传递过程中一定要写 chain.doFilter()

1.1.6. 过滤器的初始化参数

容器启动之后,会创建过滤器实例。通过init方法来完成过滤器的初始化。初始化时可以添加一些配置,提升动态性。而这些参数通过在web.xml文件中的<init-param>以name-value对的形式存在。

读取这些name-value对需要使用FilterConfig对象,从web.xml文件到FilterConfig对象的过程由容器完成,并通过参数传入到init方法之中,只需要设定一些成员对象保存数值就可以在doFilter方法中使用。

1.1.7. 初始化参数的配置

在web.xml文件中添加过滤器初始化参数的配置代码如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="2.4"
  3.     xmlns="http://java.sun.com/xml/ns/j2ee"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  6.     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  7. <!-- 过滤器 -->
  8. <filter>
  9.     <filter-name>filter1</filter-name>
  10.     <filter-class>web.CommentFilter1</filter-class>
  11.     <!-- 初始化参数 -->
  12. </filter>
  13. <filter-mapping>
  14.     <filter-name>filter1</filter-name>
  15.     <url-pattern>/comment</url-pattern>
  16. </filter-mapping>
  17. </web-app>

1.1.8. 读取初始化参数

读取初始化参数使用如下代码:

  1. public class CommentFilter implements Filter{
  2.         public void init(FilterConfig arg0) throws ServletException {
  3.             config = arg0;
  4.         }
  5.         public void doFilter(ServletRequest arg0,
  6.                              ServletResponse arg1, FilterChain arg2)
  7.                              throws IOException, ServletException {
  8.                 String illegalStr = config.getInitParameter("illegalStr");
  9.              // … …
  10.         }
  11. public void destroy() {
  12.              // … …
  13.          }
  14. }

1.1.9. 过滤器的特点

方便增加或减少某个功能模块,需要添加过滤就多部署一个class修改一下web.xml文件,需要减少某个功能只要删除web.xml中对应的声明即可。

方便修改处理逻辑。当把一些功能独立到某个模块时,如果逻辑变了,只修改这一个文件并更新就可以实现功能的改变,而不用修改每一个使用这个插件的组件。

过滤器

标签:web应用

原文地址:http://blog.csdn.net/u011707402/article/details/45752613

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!