1. 程式人生 > >Servlet編程專題9之Servlet規範中的過濾器

Servlet編程專題9之Servlet規範中的過濾器

filter生命周期 <dispatcher>標簽的四種取值 filter的特征 filter的執行原理

1、Filter基礎:

- Filter是Servlet規範的三大組件之一。顧名思義,就是過濾。可以在請求到達目標資源之前先對請求進行攔截過濾,即對請求進行一些處理;也可以在響應到達客戶端之前先對響應進行攔截過濾,即對響應進行一些處理。

技術分享


2、Filter的生命周期:

a、Filter的生命周期與Servlet的生命周期類似,其主要生命周期階段有四個:Filter對象的創建、Filter對象的初始化、Filter執行doFilter()方法以及最終Filter對象被銷毀。

- Filter的整個生命周期過程的執行,均由Web服務器負責管理。即Filter從創建到銷毀的整個過程中方法的調用,都是由Web服務器負責調用執行的,程序員無法控制其執行流程。

技術分享


- 過濾器生命周期示例:

- 自定義的Filter類需要實現Filter接口(javax.servlet.Filter),並實現其接口中定義的方法:

技術分享


- 自定義Servlet類:

技術分享


- 需要註意的是,需要在web.xml中註冊filter:

技術分享


- 啟動服務器,訪問項目中的/some路徑資源,在控制臺中顯示的結果為其生命周期:

技術分享

技術分享


- 上例中的接口以及方法的解釋:

- javax.servlet.Filter接口:過濾器是用於過濾請求資源(servlet、靜態資源)或者是從資源響應客戶端的過濾任務:(或者是兩者兼而有之)

技術分享

- 其接口中三個定義方法:

技術分享


- javax.servlet.FilterChain接口:FilterChain接口類對象是被用於servlet容器提供給開發者從視圖到資源過濾請求的調用鏈的對象。過濾器使用過濾器鏈來調用鏈中的下一個過濾器,如果正在調用的過濾器是鏈中的最後一個,則會直接調用鏈末尾端的資源。

技術分享

- 該接口中只定義一個方法:調用過濾器鏈中的下一個過濾器,或者如果正在調用的過濾器是鏈中的最後一個,則會直接調用鏈末尾端的資源。

技術分享


b、Filter的特征:

- Filter是單例多線程的。

- Filter是在應用被加載時創建並初始化的,這是與Servlet不同的地方。Servlet是在該Servlet被第一次訪問時創建的。Filter與Servlet的共同點是,其無參構造器與init()方法只會執行一次。

- 用戶每提交一次該Filter可以過濾的請求,服務器就會執行一次doFilter()方法,即doFilter()方法可以被多次執行。

- 當應用被停止時執行destroy()方法,Filter被銷毀,即destroy()方法只會執行一次。

- 由於Filter是單例多線程的,所以為了保證其線程安全性,一般情況下是不為Filter類定義可修改的成員變量。因為每個線程均可修改這個成員變量,會出現線程安全問題。


3、javax.servlet.FilterConfig接口:通常指代filter在web.xml中的註冊信息:

技術分享

- FilterConfig接口中的方法可以獲取關於當前Filter在web.xml中的信息:(ServletContext、filterName、initParameter等):

技術分享


- FilterConfig接口中的方法在filter類中使用的示例:

- 可以在自定義Filter類中定義私有化的成員變量(並提供getFilterConfig()方法),在init(FilterConfig filterConfig)方法接收。在doFilter方法中使用這個filterConfig成員變量:

技術分享


- 需要註意的是,在web.xml中的<filter>標簽中,可以提供<init-param>標簽,以提供初始化參數:

技術分享

- 當訪問一個index.jsp頁面時,控制臺中的打印如下:

技術分享


4、<dispatcher>標簽的四種取值:

- 在<filter-mapping>中還有一個子標簽<dispatcher>,用於設置過濾器的請求類型。其有四種取值,REQUEST、FORWARD、INCLUDE、ERROR。

- FORWARD:若請求是由一個Servlet通過RequestDsipatcher的forward()方法所轉發的,那麽這個請求將被<dispatcher>值為FORWARD的Filter所攔截。即當前Filter只會攔截由RequestDispatcher的forward()方法所轉發的請求。其他請求均

不攔截。

技術分享


- INCLUDE:當前Fillter只會攔截由RequestDsipatcher的include()方法所轉發的請求。其他請求均不攔截。

技術分享


- REQUEST:表示當前過濾其只會攔截普通請求,但是對forward和include的跳轉不進行攔截。(默認值)

- ERROR:表示當跳轉到指定的錯誤處理頁面時,這個跳轉請求會被當前過濾器攔截。


- <dispatcher>標簽的ERROR取值示例:

- 在web.xml中填寫如下代碼,使得當跳轉到指定的錯誤處理頁面時,這個跳轉請求會被當前過濾器攔截。

技術分享


5、多個Filter的執行順序問題:

技術分享

- 當應用中存在多個Filter時,其執行順序與註冊順序一致。(如上圖所示,先執行OneFilter的請求過濾攔截,再是TwoFilter的請求過濾攔截,後是SomeServlet的執行,後是TwoFilter的響應過濾攔截,最後是TwoFilter的請求過濾攔截)


6、Filter的執行原理:

- 當某資源的請求到達Web容器時,會先對請求進行解析,使用解析出來的URI作為比較對象,從Map(Map的key為<url-pattern>的值,value為Filter實例對象的引用)中查找是否存在相匹配的key。若存在,那麽讀取其value,即Filter對象的引用,將該引用存入到數組中。然後繼續向後查找,直到將該Map查找完畢。這樣在數組中就存在按照查找順序排好序的Filter引用。

- 數組初始化完畢後,開始按照數組元素順序進行執行。所以數組中的Filter全部執行完畢之後,再跳轉到請求的目標資源。(數組中存放著與請求相匹配的所有Filter)


7、附加說明:

a、若Filter為全路徑匹配方式,那麽url-pattern只能寫為/*,而不能夠寫為/。(寫為/,無論是靜態資源,還是動態資源都不起作用)

- <filter-mapping>標簽中可以不使用<url-pattern>,但需要指定<servlet-name>,即當前過濾器攔截的是對指定Servlet的請求。


b、filter過濾器的應用:

- 可以在自定義的過濾器(MyCharactorEncodingFilter類)中解決POST提交中文亂碼問題。

技術分享

本文出自 “12392717” 博客,請務必保留此出處http://12402717.blog.51cto.com/12392717/1977105

Servlet編程專題9之Servlet規範中的過濾器