責任鏈模式是一種對象的行爲模式。在責任鏈模式裏,不少對象由每個對象對其下家的引用而鏈接起來造成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪個對象最終處理這個請求,這使得系統能夠在不影響客戶端的狀況下動態地從新組織和分配責任。java
一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行爲中選擇一個:一是承擔責任,而是把責任推給下家。不容許出現某一個具體處理者對象在承擔了一部分責任後又 把責任向下傳的狀況。web
在一個純的責任鏈模式裏面,一個請求必須被某一個處理者對象所接收;在一個不純的責任鏈模式裏面,一個請求能夠最終不被任何接收端對象所接收。數組
純的責任鏈模式的實際例子很難找到,通常看到的例子均是不純的責任鏈模式的實現。有些人認爲不純的責任鏈根本不是責任鏈模式,這也許是有道理的。可是在實際的系統裏,純的責任鏈很難找到。若是堅持責任鏈不純便不是責任鏈模式,那麼責任鏈模式便不會有太大意義了。app
衆所周知Tomcat中的Filter就是使用了責任鏈模式,建立一個Filter除了要在web.xml文件中作相應配置外,還須要實現javax.servlet.Filter接口。this
public class TestFilter implements Filter{ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); } public void destroy() { } public void init(FilterConfig filterConfig) throws ServletException { } }
使用DEBUG模式所看到的結果以下spa
其實在真正執行到TestFilter類以前,會通過不少Tomcat內部的類。順帶提一下其實Tomcat的容器設置也是責任鏈模式,注意被紅色方框所圈中的類,從Engine到Host再到Context一直到Wrapper都是經過一個鏈傳遞請求。被綠色方框所圈中的地方有一個名爲ApplicationFilterChain的類,ApplicationFilterChain類所扮演的就是抽象處理者角色,而具體處理者角色由各個Filter扮演。code
第一個疑問是ApplicationFilterChain將全部的Filter存放在哪裏?xml
答案是保存在ApplicationFilterChain類中的一個ApplicationFilterConfig對象的數組中。對象
那ApplicationFilterConfig對象又是什麼呢?blog
ApplicationFilterConfig是一個Filter容器。
當一個web應用首次啓動時ApplicationFilterConfig會自動實例化,它會從該web應用的web.xml文件中讀取配置的Filter的信息,而後裝進該容器。
剛剛看到在ApplicationFilterChain類中所建立的ApplicationFilterConfig數組長度爲零,那它是在何時被從新賦值的呢?
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
是在調用ApplicationFilterChain類的addFilter()方法時。
變量n用來記錄當前過濾器鏈裏面擁有的過濾器數目,默認狀況下n等於0,ApplicationFilterConfig對象數組的長度也等於0,因此當第一次調用addFilter()方法時,if (n == filters.length)的條件成立,ApplicationFilterConfig數組長度被改變。以後filters[n++] = filterConfig;將變量filterConfig放入ApplicationFilterConfig數組中並將當前過濾器鏈裏面擁有的過濾器數目+1。
那ApplicationFilterChain的addFilter()方法又是在什麼地方被調用的呢?
是在ApplicationFilterFactory類的createFilterChain()方法中。
能夠將如上代碼分爲兩段,51行以前爲第一段,51行以後爲第二段。
第一段的主要目的是建立ApplicationFilterChain對象以及一些參數設置。
第二段的主要目的是從上下文中獲取全部Filter信息,以後使用for循環遍歷並調用filterChain.addFilter(filterConfig);將filterConfig放入ApplicationFilterChain對象的ApplicationFilterConfig數組中。
那ApplicationFilterFactory類的createFilterChain()方法又是在什麼地方被調用的呢?
是在StandardWrapperValue類的invoke()方法中被調用的。
那正常的流程應該是這樣的:
在StandardWrapperValue類的invoke()方法中調用ApplicationFilterChai類的createFilterChain()方法———>在ApplicationFilterChai類的createFilterChain()方法中調用ApplicationFilterChain類的addFilter()方法———>在ApplicationFilterChain類的addFilter()方法中給ApplicationFilterConfig數組賦值。
根據上面的代碼能夠看出StandardWrapperValue類的invoke()方法在執行完createFilterChain()方法後,會繼續執行ApplicationFilterChain類的doFilter()方法,而後在doFilter()方法中會調用internalDoFilter()方法。
這裏的filter.doFilter(request, response, this);就是調用咱們前面建立的TestFilter中的doFilter()方法。而TestFilter中的doFilter()方法會繼續調用chain.doFilter(request, response);方法,而這個chain其實就是ApplicationFilterChain,因此調用過程又回到了上面調用dofilter和調用internalDoFilter方法,這樣執行直到裏面的過濾器所有執行。
因爲invoke()方法較長,因此將不少地方省略。