对过滤器(filter)的一点小思考

前言

       我们知道,假如我们在web应用中 设置了三个过滤器 1,2,3,那么执行流程应该是

                  过滤器1》过滤器2》过滤器3》具体业务》过滤器3》过滤器2》过滤器1

        我当初想web容器是如何做到这个执行顺序的呢,最开始考虑的就是 是否采用的动态代理,因为相当于对 业务方法进行了 加强,但是仔细一想,如果是通过 动态代理,那么 业务方法 执行前应该是一个代码段   执行后应该是一个代码段,那 filter 的设计应该是 有一个 start()方法,一个 end()方法,但很明显 filter 的方法不是这样的。偶然点进去了一个 FilterChain 的实现类

public class MockFilterChain implements FilterChain {
    private ServletRequest request;
    private ServletResponse response;
    private final List<Filter> filters;
    private Iterator<Filter> iterator;
    
    //......中间忽略

public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        Assert.notNull(request, "Request must not be null");
        Assert.notNull(response, "Response must not be null");
        if (this.request != null) {
            throw new IllegalStateException("This FilterChain has already been called!");
        } else {
            if (this.iterator == null) {
                this.iterator = this.filters.iterator();
            }

            if (this.iterator.hasNext()) {
                Filter nextFilter = (Filter)this.iterator.next();
                nextFilter.doFilter(request, response, this);
            }

            this.request = request;
            this.response = response;
        }
    }
}

然后自己简单模拟了一下

尝试

      

//过滤器接口
package TestFilterChain.iface;

import TestFilterChain.MyFilterChain;

import java.util.Map;

/**
 * @date 2018/7/31 12:36
 * @description
 */
public interface MyFilter {
    void doFilter(Map<String,Object> param, MyFilterChain filterChain);
}

//servlet接口
package TestFilterChain.iface;

/**
 * @date 2018/7/31 12:51
 * @description
 */
public interface MyServlet {
    void doPost();
    void doGet();
}

//过滤器实现类
package TestFilterChain.impl;

import TestFilterChain.MyFilterChain;
import TestFilterChain.iface.MyFilter;

import java.util.Map;

/**
 * @date 2018/7/31 12:54
 * @description
 */
public class MyFilterImpl implements MyFilter{
    @Override
    public void doFilter(Map<String, Object> param, MyFilterChain filterChain) {
        System.out.println("请求参数:"+param.toString());

        filterChain.doFilter();

        System.out.println("请求结束");
    }
}

// servlet实现类
package TestFilterChain.impl;

import TestFilterChain.iface.MyServlet;

/**
 * @date 2018/7/31 12:53
 * @description
 */
public class MyServletImpl implements MyServlet {
    @Override
    public void doPost() {
        System.out.println("处理逻辑");
    }

    @Override
    public void doGet() {
        doPost();
    }
}

//拦截器链模拟类
package TestFilterChain;

import TestFilterChain.iface.MyFilter;
import TestFilterChain.iface.MyServlet;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @date 2018/7/31 12:35
 * @description
 */
public class MyFilterChain {
    /**
     * 需要执行的任务
     */
    private MyServlet myServlet;
    /**
     * 封装请求参数
     */
    private Map<String,Object> args;

    /**
     * 过滤器集合
     */
    private List<MyFilter> myFilterList;

    /**
     * 迭代器
     */
    private Iterator<MyFilter> iterator;

    public MyFilterChain(List<MyFilter> myFilterList,Map<String,Object> args,MyServlet myServlet) {
        this.myFilterList = myFilterList;
        this.args = args;
        this.myServlet = myServlet;
        iterator = myFilterList.iterator();
        myFilterList.subList(0,1);
    }

    public List<MyFilter> getMyFilterList() {
        return myFilterList;
    }

    public void setMyFilterList(List<MyFilter> myFilterList) {
        this.myFilterList = myFilterList;
    }

    /**
     * 执行filter链的入口
     */
    public void doFilter(){
        if (iterator.hasNext()){
            iterator.next().doFilter(args,this);
        }else {
            //执行servlet的逻辑
            myServlet.doGet();
        }
    }
}

//web 容器模拟类
package TestFilterChain;

import TestFilterChain.iface.MyFilter;
import TestFilterChain.iface.MyServlet;
import TestFilterChain.impl.MyFilterImpl;
import TestFilterChain.impl.MyServletImpl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @date 2018/7/31 12:57
 * @description
 */
public class WebContainer {
    //处理一个请求
    public static void main(String[] args) {
        //模拟请求参数
        Map<String,Object> param = new HashMap<>();
        param.put("userName","111111");
        param.put("password","222222");

        //模拟处理的servlet
        MyServlet servlet = new MyServletImpl();

        //模拟定义的 List<filter>
        List<MyFilter> filters = new ArrayList<>();
        MyFilter filter = new MyFilter() {
            @Override
            public void doFilter(Map<String, Object> param, MyFilterChain filterChain) {
                System.out.println("filter_1 start");
                filterChain.doFilter();
                System.out.println("filter_1 end");
            }
        };
        MyFilter filter2 = new MyFilter() {
            @Override
            public void doFilter(Map<String, Object> param, MyFilterChain filterChain) {
                System.out.println("filter_2 start");
                filterChain.doFilter();
                System.out.println("filter_2 end");
            }
        };
        filters.add(filter);
        filters.add(filter2);

        //执行
        MyFilterChain filterChain = new MyFilterChain(filters,param,servlet);
        filterChain.doFilter();
    }
}




//输出结果
filter_1 start
filter_2 start
处理逻辑
filter_2 end
filter_1 end

总结

      我理解的流程是:

      当客户端发送一个请求时,web容器对这个请求处理过程:

            1.根据url 路径,匹配对应的 filter/servlet

            2.封装 HttpServletRequest 与 HttpServletResponse 对象

            3.把 filter/servlet/req/res 封装到一个拦截器链对象中

            4.调用拦截器链对象的 doFilter() 方法

            5.doFilter() 方法中,先尝试从过滤器结合的迭代器中获取过滤器。如果获取到,就执行过滤器的 doFilter() 方法,并把过滤器链一起传给过滤器,过滤器控制是否再执行 过滤器链 的 doFilter() 方法。如果没获取到,说明过滤器执行完毕或无过滤器需要执行,则执行 业务逻辑方法。感觉很像一个递归

后记

       以上纯属个人的一些理解,有不对的地方还请大家指出来。

猜你喜欢

转载自blog.csdn.net/zaige66/article/details/81413231
今日推荐