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方法是對過濾器進(jìn)行初始化的,最重要的是doFilter方法,這個(gè)方法有三個(gè)參數(shù),前兩個(gè)參數(shù)也簡單就是外部傳入Servlet請求和響應(yīng)對象,可以用這兩個(gè)對象進(jìn)行進(jìn)行判斷過濾操作,最后一個(gè)參數(shù)是FilterChain filterChain官方叫做*過濾鏈*,開始學(xué)習(xí)就知道,在doFilter方法中調(diào)用filterChain.doFilter(servletRequest,servletResponse)就可以放行將請求傳遞給下一個(gè)過濾,如果不調(diào)用這個(gè)方法直接用response輸出響應(yīng),說明這個(gè)請求被攔截了:

代碼如下:

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

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

這個(gè)FilterChain是如何實(shí)現(xiàn)的呢,為什么可以將多個(gè)過濾器Filter組成一個(gè)鏈,當(dāng)我想一探源碼面貌的時(shí)候,javaee只提供了接口,具體實(shí)現(xiàn)由web容器(比如tomcat)提供的,但是tomcat的代碼不是開源的,因此無法查看。這是多年一直有的困惑,直到看到Spring SecurityFilterChainProxy的內(nèi)部類VirtualFilterChain實(shí)現(xiàn)才恍然大悟,這個(gè)是類是Spring Security實(shí)現(xiàn)虛擬過濾器FilterChain的一個(gè)類,為了方便去掉無關(guān)代碼:

首先看屬性:

  1. additionalFilters用來保存組成過濾鏈的Filter;
  2. size用來保存過濾鏈Filter的數(shù)目;
  3. currentPosition用來保存當(dāng)前執(zhí)行到哪個(gè)過濾器Filter。

然后看doFilter方法內(nèi)部: 從additionalFilters屬性按照currentPosition下標(biāo)取出Filter對象,然后調(diào)用它們的doFilter方法,最關(guān)鍵是傳入的參數(shù):nextFilter.doFilter(request, response, this);,注意最后一個(gè)參數(shù)是將當(dāng)前對象傳入每個(gè)FilterFilterChain參數(shù),這就能解釋為什么如果在FilterdoFilter方法內(nèi)部執(zhí)行filterChain.doFilter(response,response);就可以將請求傳入到下一個(gè)過濾器了,明白過程,不妨畫個(gè)圖來加深映像:

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

        private VirtualFilterChain(FilterChain chain, List<Filter> 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都順利執(zhí)行后 轉(zhuǎn)到真實(shí)filter
                this.originalChain.doFilter(request, response);
            } else {
                ++this.currentPosition;
                Filter nextFilter = (Filter)this.additionalFilters.get(this.currentPosition - 1);


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

        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容