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

Filter的执行顺序与实例

时间:2018-01-21 16:20:36      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:path   介绍   arc   实现   des   需要   xml文件   改变   str   

 Filter介绍 

Filter可认为是Servlet的一种“变种”,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理,是个典型的处理链。它与Servlet的区别在于:它不能直接向用户生成响应。完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

Filter有如下几个用处。

  • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
  • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
  • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse。
  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

Filter有如下几个种类。

  • 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
  • 日志Filter:详细记录某些特殊的用户请求。
  • 负责解码的Filter:包括对非标准编码的请求解码。
  • 能改变XML内容的XSLT Filter等。
  • Filter可负责拦截多个请求或响应;一个请求或响应也可被多个请求拦截。

创建一个Filter只需两个步骤:

  • 建Filter处理类;
  • web.xml文件中配置Filter。

下面先介绍一个简单的记录日志的Filter,这个Filter负责拦截所有的用户请求,并将请求的信息记录在日志中。

public class LogFilter implements Filter {

    /**
     * FilterConfig可用于访问Filter的配置信息
     */
    private FilterConfig config;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.config = config;
    }

    /**
     * 执行过滤的核心方法
     *
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //---------下面代码用于对用户请求执行预处理---------
        //获取ServletContext对象,用于记录日志
        ServletContext context = this.config.getServletContext();
        long before = System.currentTimeMillis();
        System.out.println("开始过滤...");
        //将请求转换成HttpServletRequest请求
        HttpServletRequest hrequest = (HttpServletRequest) request;
        //记录日志
        context.log("Filter已经截获到用户的请求地址: " + hrequest.getServletPath());
        //Filter只是链式处理,请求依然放行到目的地址
        chain.doFilter(request, response);
        //---------下面代码用于对服务器响应执行后处理---------
        long after = System.currentTimeMillis();
        //记录日志
        context.log("过滤结束");
        //再次记录日志
        context.log("请求被定位到" + hrequest.getRequestURI() + "所花的时间为: " + (after - before));
    }

    @Override
    public void destroy() {
        this.config = null;
    }
}

 上面程序实现了doFilter()方法,实现该方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理——它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。

在上面的请求Filter中,仅在日志中记录请求的URL,对所有的请求都执行chain.doFilter (request,reponse)方法,当Filter对请求过滤后,依然将请求发送到目的地址。如果需要检查权限,可以在Filter中根据用户请求的HttpSession,判断用户权限是否足够。如果权限不够,直接调用重定向即可,无须调用chain.doFilter(request,reponse)方法。

 FirstFilter.java 

public class FirstFilter implements Filter {

    @Override
    public void destroy() {
        System.out.println("1st destroy()...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        System.out.println("before invoke 1stFilter‘s chain.doFilter() ..");
        chain.doFilter(request, response);
        System.out.println("after invoke 1stFilter‘s chain.doFilter() ..");
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("1stFilter init()...");
    }
}

SecondFilter.java 

public class SecondFilter implements Filter {

    @Override
    public void destroy() {
        System.out.println("2ndFilter destroy()...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        System.out.println("before invoke 2ndFilter‘s chain.doFilter() ..");
        chain.doFilter(request, response);
        System.out.println("after invoke 2ndFilter‘s chain.doFilter() ..");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2ndFilter init()...");
    }
}

MyServlet.java 

public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("servlet doGet be invoked...");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        this.doGet(req, resp);
    }
}

web.xml  

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <filter>
        <filter-name>firstFilter</filter-name>
        <filter-class>com.winner.FirstFilter</filter-class>
    </filter>
    <filter>
        <filter-name>secondFilter</filter-name>
        <filter-class>com.winner.SecondFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>secondFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>firstFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.winner.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>
</web-app>

然后发布,发现打印的日志如下:

1stFilter init()...
2ndFilter init()...

这里过滤器初始化好了。

当我们访问我们的 应用:http://localhost:8080/MyServlet

before invoke 2ndFilter‘s chain.doFilter() ..
before invoke 1stFilter‘s chain.doFilter() ..
servlet doGet be invoked...
after invoke 1stFilter‘s chain.doFilter() ..
after invoke 2ndFilter‘s chain.doFilter() ..

当我们将web.xml中filter的位置进行调整后(注意filter-mapping的顺序):

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <filter>
        <filter-name>firstFilter</filter-name>
        <filter-class>com.winner.FirstFilter</filter-class>
    </filter>
    <filter>
        <filter-name>secondFilter</filter-name>
        <filter-class>com.winner.SecondFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>firstFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>secondFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.winner.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>
</web-app>

当我们访问我们的 应用:http://localhost:8080/MyServlet

before invoke 1stFilter‘s chain.doFilter() ..
before invoke 2ndFilter‘s chain.doFilter() ..
servlet doGet be invoked...
after invoke 2ndFilter‘s chain.doFilter() ..
after invoke 1stFilter‘s chain.doFilter() ..

技术分享图片

Filter的执行顺序与实例

标签:path   介绍   arc   实现   des   需要   xml文件   改变   str   

原文地址:https://www.cnblogs.com/winner-0715/p/8324270.html

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