關於Filter執行順序的探究
今天研究一下Filter的執行順序問題。
首先,我寫了三個Filter
三個Filter的內容是一樣的,用不同列印來區分,這裡我只給出FirstFiler為例
package com.zhwy.filters; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.Filter; public class FirstFilter implements Filter{ public void init(FilterConfig config) throws ServletException { //獲取初始化引數 String first = config.getInitParameter("First"); System.out.println(first); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException { System.out.println("This is FirstFilter..."); //把請求傳回過濾鏈 chain.doFilter(request, response); System.out.println("FirstFilter over!"); } public void destroy(){ System.out.println("FirstFilter was destroyed"); } }
我們先以正常順序走一遍:
web.xml檔案配置如下:
<!--過濾器1 --> <filter> <filter-name>LogFilter</filter-name> <filter-class>com.zhwy.filters.FirstFilter</filter-class> <init-param> <param-name>First</param-name> <param-value>第一個Filter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--過濾器2 --> <filter> <filter-name>LogFilter2</filter-name> <filter-class>com.zhwy.filters.SecondFilter</filter-class> <init-param> <param-name>Second</param-name> <param-value>第二個Filter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--過濾器3 --> <filter> <filter-name>LogFilter3</filter-name> <filter-class>com.zhwy.filters.ThirdFilter</filter-class> <init-param> <param-name>Third</param-name> <param-value>第三個Filter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter3</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
首先Tomcat載入專案,Filter初始化,執行init() 方法,列印如下:
訪問index.jsp,列印如下:
可以看出,doFilter()最初執行時是按順序執行的,當執行完所有Filter鏈時,又從最近的這個Filter返回執行。
下面我將ThirdFilter的所有配置資訊在web.xml中移至最前面,即3-1-2的順序。
<!--過濾器3 --> <filter> <filter-name>LogFilter3</filter-name> <filter-class>com.zhwy.filters.ThirdFilter</filter-class> <init-param> <param-name>Third</param-name> <param-value>第三個Filter</param-value> </init-param> </filter> <filter-mapping> <filter-name>LogFilter3</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--過濾器1 -->
...
<!--過濾器2 -->
...
Tomcat載入如下:
訪問index.jsp:
可以看出,doFilter()依然按web.xml中的順序執行,執行完Filter鏈時,依然原路返回。
但是,最初的init()方法卻依然記憶了上一次的順序。
接著我僅將ThirdFilter的配置資訊提前,而仍然將其對映<filter-mapping>放在後面
<!--過濾器3 -->
<filter>
<filter-name>LogFilter3</filter-name>
<filter-class>com.zhwy.filters.ThirdFilter</filter-class>
<init-param>
<param-name>Third</param-name>
<param-value>第三個Filter</param-value>
</init-param>
</filter>
<!--過濾器1 -->
...
<!--過濾器2 -->
...
<filter-mapping>
<filter-name>LogFilter3</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
初始化順序依然保留記憶
而訪問index時,filter的執行順序是按照對映資訊順序,即<filter-mapping>順序執行的
綜上,
在doFilter()方法中,
在chain.doFilter()方法之前,
doFilter()的執行順序是按照web.xml中的配置順序執行的,確切的說,按照<filter-mapping>的順序執行的。
而呼叫完chain.doFilter()方法後,即當filter鏈中的filter都按順序執行完畢,像堆疊一樣,filter又從最近的一個開始執行。
另外,
在init()方法中,
似乎只按照容器第一次載入時初始化的順序執行,其後的順序不會影響。
最後,
關於destroy()方法,
只有在與容器斷開,即使用者與伺服器斷開,session結束時才會呼叫。