過濾器詳細
1 過濾器的生命周期
我們已經學習過Servlet的生命周期,那么Filter的生命周期也就沒有什么難度了!
(l) init(FilterConfig):在服務器啟動時會創建Filter實例,並且每個類型的Filter只創建一個實例,從此不再創建!在創建完Filter實例后,會馬上調用init()方法完成初始化工作,這個方法只會被執行一次;
(l) doFilter(ServletRequest req,ServletResponse res,FilterChain chain):這個方法會在用戶每次訪問“目標資源(<url->pattern>index.jsp</url-pattern>)”時執行,如果需要“放行”,那么需要調用FilterChain的doFilter(ServletRequest,ServletResponse)方法(就是說必須寫這個函數才方形,比如上述的doFilter函數),如果不調用FilterChain的doFilter()方法,那么目標資源將無法執行;
(l) destroy():服務器會在創建Filter對象之后,把Filter放到緩存中一直使用,通常不會銷毀它。一般會在服務器關閉時銷毀Filter對象,在銷毀Filter對象之前,服務器會調用Filter對象的destory()方法。
2 FilterConfig
你已經看到了吧,Filter接口中的init()方法的參數類型為FilterConfig類型。它的功能與ServletConfig相似,與web.xml文件中的配置信息對應。下面是FilterConfig的功能介紹:
(l) ServletContext getServletContext():獲取ServletContext的方法;
(l) String getFilterName():獲取Filter的配置名稱;與<filter-name>元素對應;
(l) String getInitParameter(String name):獲取Filter的初始化配置,與<init-param>元素對應;
(l) Enumeration getInitParameterNames():獲取所有初始化參數的名稱。
3 FilterChain
doFilter()方法的參數中有一個類型為FilterChain的參數,它只有一個方法:doFilter(ServletRequest,ServletResponse)。
前面我們說doFilter()方法的放行,讓請求流訪問目標資源!但這么說不嚴密,其實調用該方法的意思是,“我(當前Filter)”放行了,但不代表其他人(其他過濾器)也放行。
也就是說,一個目標資源上,可能部署了多個過濾器,就好比在你去北京的路上有多個打劫的匪人(過濾器),而其中第一伙匪人放行了,但不代表第二伙匪人也放行了,所以調用FilterChain類的doFilter()方法表示的是執行下一個過濾器的doFilter()方法,或者是執行目標資源!
如果當前過濾器是最后一個過濾器,那么調用chain.doFilter()方法表示執行目標資源,而不是最后一個過濾器,那么chain.doFilter()表示執行下一個過濾器的doFilter()方法。
4 多個過濾器執行順序
一個目標資源可以指定多個過濾器,過濾器的執行順序是在web.xml文件中的部署順序:
<filter> <filter-name>myFilter1[崔1] </filter-name> [崔1]因為MyFilter1配置在前面,所以先執行MyFilter1的doFilter()方法。 <filter-class>cn.itcast.filter.MyFilter1</filter-class> </filter>
<filter-mapping> <filter-name>myFilter1</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping>
<filter> <filter-name>myFilter2</filter-name> <filter-class>cn.itcast.filter.MyFilter2</filter-class> </filter>
<filter-mapping> <filter-name>myFilter2</filter-name> <url-pattern>/index.jsp</url-pattern> </filter-mapping>
public class MyFilter1 extends HttpFilter { public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("filter1 start..."); chain.doFilter(request, response);//放行,執行MyFilter2的doFilter()方法 System.out.println("filter1 end..."); } } public class MyFilter2 extends HttpFilter { public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("filter2 start..."); chain.doFilter(request, response);//放行,執行目標資源 System.out.println("filter2 end..."); } } <body> This is my JSP page. <br> <h1>index.jsp</h1> <%System.out.println("index.jsp"); %> </body>
當有用戶訪問index.jsp頁面時,輸出結果如下:
filter1 start... filter2 start... index.jsp filter2 end... filter1 end... |