Filter过滤器理解

Filter过滤器,在java中它的接口如下:

import java.io.IOException;

public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest response, ServletResponse response, FilterChain filterChain) throws IOException, ServletException;

    default void destroy() {
    }
}

其中,init方法、destory方法是对过滤器进行初始化的,最重要的是doFilter方法,这个方法有三个参数,前两个参数也简单就是外部传入Servlet请求和响应对象,可以用这两个对象进行进行判断过滤操作,最后一个参数是FilterChain filterChain官方叫做*过滤链*,开始学习就知道,在doFilter方法中调用filterChain.doFilter(servletRequest,servletResponse)就可以放行将请求传递给下一个过滤,如果不调用这个方法直接用response输出响应,说明这个请求被拦截了:

代码如下:

 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

            throws IOException, ServletException {
     
     // 之前做些过滤操作
     filterChain.doFilter(response,response);
 }

这个FilterChain是如何实现的呢,为什么可以将多个过滤器Filter组成一个链,当我想一探源码面貌的时候,javaee只提供了接口,具体实现由web容器(比如tomcat)提供的,但是tomcat的代码不是开源的,因此无法查看。这是多年一直有的困惑,直到看到Spring SecurityFilterChainProxy的内部类VirtualFilterChain实现才恍然大悟,这个是类是Spring Security实现虚拟过滤器FilterChain的一个类,为了方便去掉无关代码:

首先看属性:

  1. additionalFilters用来保存组成过滤链的Filter;
  2. size用来保存过滤链Filter的数目;
  3. currentPosition用来保存当前执行到哪个过滤器Filter

然后看doFilter方法内部: 从additionalFilters属性按照currentPosition下标取出Filter对象,然后调用它们的doFilter方法,最关键是传入的参数:nextFilter.doFilter(request, response, this);,注意最后一个参数是将当前对象传入每个FilterFilterChain参数,这就能解释为什么如果在FilterdoFilter方法内部执行filterChain.doFilter(response,response);就可以将请求传入到下一个过滤器了,明白过程,不妨画个图来加深映像:

image-20210930132108506.png
private static class VirtualFilterChain implements FilterChain {    
        private final List additionalFilters;
        private final int size;
        private int currentPosition;

        private VirtualFilterChain(FilterChain chain, List additionalFilters) {
            this.currentPosition = 0;
            this.additionalFilters = additionalFilters;
            this.size = additionalFilters.size();
        }

        public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
            if (this.currentPosition == this.size) {
                //过滤链的Filter都顺利执行后 转到真实filter
                this.originalChain.doFilter(request, response);
            } else {
                ++this.currentPosition;
                Filter nextFilter = (Filter)this.additionalFilters.get(this.currentPosition - 1);


                nextFilter.doFilter(request, response, this);
            }

        }
    }

你可能感兴趣的:(Filter过滤器理解)