码迷,mamicode.com
首页 > 编程语言 > 详细

JavaWeb三大组件之Filter

时间:2018-10-26 17:41:26      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:输出   bsp   size   请求   []   情况   throws   并发   接口   

一、Filter作用

对请求或者响应进行拦截,并做额外的逻辑处理

filter能在一个请求访问目标资源之前对其进行拦截然后做某些逻辑处理,例如权限检查,也可以在一个输出响应到达客户端之前对其进行拦截

并做一些额外的操作(例如,设置响应编码格式)。

二、接口定义

技术分享图片
public abstract interface Filter{
    public abstract void init(FilterConfig filterConfig) throws ServletException;
    public abstract void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException;
    public abstract void destroy();
}
View Code

三、执行原理分析

当客户端发送一个请求访问某个资源时,Servlet容器会根据web.xml中的配置找出该请求所有匹配的过滤器,并保存到一个数组中

从而形成一个过滤器链,链中的每个过滤器都是一个处理节点。然后通过调用Tomcat服务器中的ApplicationFilterChain对象中的doFilter方法

不断迭代执行数组中的过滤器中的doFilter方法对请求和响应进行额外的逻辑处理(因为过滤器中的doFilter方法会重新调用FilterChain中的doFilter方法)。

Filter其实就是基于回调函数实现的责任链模式的应用。

模拟Servlet容器执行过滤器的场景: 

技术分享图片
import java.util.List;

class Scratch {
    public static void main(String[] args) {
        new ApplicationFilterChain().doFilter(new ServletRequest(), new ServletResponse());
    }

    public static interface Filter {
        void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain);
    }

    /**
     * 自定义过滤器
     */
    public static class MyFilter1 implements Filter {
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
            System.out.println("即将执行过滤器1");
            //回调方法,用于调用链中的下一个过滤器
            filterChain.doFilter(request, response);
            System.out.println("已经执行过滤器1");
        }
    }

    /**
     * 自定义过滤器
     */
    public static class MyFilter2 implements Filter {
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
            System.out.println("即将执行过滤器2");
            //回调方法,用于调用链中的下一个过滤器
            filterChain.doFilter(request, response);
            System.out.println("已经执行过滤器2");
        }
    }

    /**
     * 自定义过滤器
     */
    public static class MyFilter3 implements Filter {
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
            System.out.println("即将执行过滤器3");
            //回调方法,用于调用链中的下一个过滤器
            filterChain.doFilter(request, response);
            System.out.println("已经执行过滤器3");
        }
    }

    /**
     * 模拟过滤器链接口
     */
    public static interface FilterChain {
        void doFilter(ServletRequest request, ServletResponse response);
    }

    /**
     * 模拟ApplicationFilterChain
     */
    public static class ApplicationFilterChain implements FilterChain {
        //模拟注册的过滤器,保存在一个数组中
        Filter[] filters = new Filter[]{new MyFilter1(), new MyFilter2(), new MyFilter3()};
        //用于保存遍历过滤器数组的下标
        private int pos = 0;

        /**
         * 开始执行过滤器逻辑
         */
        public void doFilter(ServletRequest request, ServletResponse response) {
            //pos小于过滤器数组中的元素说明过滤器还没执行完
            if (pos < filters.length) {
                //调用过滤器的doFilter方法,并将this这个当前对象传递进去
                filters[pos++].doFilter(request, response, this);
            }
        }
    }

    /**
     * 模拟请求对象
     */
    public static class ServletRequest {

    }

    /*
     * 模拟响应对象
     * */
    public static class ServletResponse {

    }
}
View Code

 结果如下:

技术分享图片

四、Filter的生命周期

Filter类似于Servlet,其对象的创建和销毁由Servlet容器负责。当Servlet容器启动的时候,将创建Filter实例对象,并调用其init()方法

进行一些初始化操作。当Servlet容器关闭或者重启时,将调用Filter对象的destory()方法,以释放相应的资源。init()和destory()方法在Filter对象的

整个生命周期中都只仅会执行一次。当客户端有多个并发请求访问某个资源的时候,doFilter方法可能同时在多个线程环境中被执行,

因此有可能出现并发安全问题,需要尽量确保doFilter方法中不会出现操作全局变量的情况。

五、配置Filter

1、xml方法配置

技术分享图片
  <filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.demo.web.MyFilter</filter-class>
  </filter>
  <servlet-mapping>
    <servlet-name>MyFilter</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
View Code

使用xml配置注解时,默认配置在前面的Filter会先执行。

另外,filterMapping中还可以通过<dispatcher>节点配置指示Servlet容器拦截何种方式的资源。

1、REQUEST:只拦截用户直接访问的资源(默认)。

2、INCLUDE:只拦截通过RequestDispatcher的include()方法访问的资源。

3、FORWARD:只拦截通过RequestDispatcher的forward()方法访问的资源。

3、ERROR:只拦截通过声明式异常处理机制调用的资源。

2、使用注解配置

技术分享图片
@WebFilter(filterName="MyFilter",urlPatterns={"/*"})
View Code

 

JavaWeb三大组件之Filter

标签:输出   bsp   size   请求   []   情况   throws   并发   接口   

原文地址:https://www.cnblogs.com/Jabben_Yi/p/9851157.html

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