Servlet三大元件_Filter過慮器
Filter過慮器
Filter(過濾器)用於攔截使用者請求,在伺服器作出響應前,可以在攔截後修改request和response。可以實現一次編碼,多處應用。Filter不像Servlet,它不能產生一個請求或者響應,它只是修改對某一資源的請求,或者修改從某一的響應。
作用:
Filter主要的作用有兩個:
- 攔截修改請求:在HttpServletRequest到達Servlet之前,攔截客戶的HttpServletRequest。根據需要檢查HttpServletRequest,也可以修改HttpServletRequest頭和資料。
- 攔截修改響應:在HttpServletResponse到達客戶端之前,攔截HttpServletResponse。根據需要檢查HttpServletResponse,也可以修改HttpServletResponse頭和資料。
原理:
通常Filter完整的工作流程是:Filter對使用者請求進行預處理,接著將請求交給Servlet進行處理並生成響應,最後Filter再對伺服器響應進行後處理。
Filter的底層原理是基於函式回撥的,很容易聯想到設計模式中的責任鏈模式
原理圖
自定義過慮器
public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { System.out.println("MyFilter......."); //對使用者請求執行預處理的程式碼邏輯 precode... //交給FilterChain的下一個物件處理 //如果還有filter則呼叫下一個filter //如果沒有,則呼叫目標資源。 chain.doFilter(req, resp);//對伺服器響應執行後處理 postcode... } @Override public void destroy() { } }
其中:
- preCode為Filter的doFilter()中chain.doFilter(request,response)呼叫之前的程式碼語句用於對使用者請求執行預處理
- postCode為Filter的doFilter()中chain.doFilter(request,response)呼叫之後的程式碼語句用於對伺服器響應執行後處理
生命週期
Filter的生命週期和Servlet一樣,Filter的建立和銷燬也是由WEB伺服器負責。
- init(FilterConfig filterConfig)
- 初始化方法,只會在web應用程式啟動時呼叫一次
- 和我們編寫的Servlet程式一樣,Filter的建立和銷燬由WEB伺服器負責。
- web 應用程式啟動時,web 伺服器將建立Filter 的例項物件,並呼叫其init方法,讀取web.xml配置,完成物件的初始化功能,從而為後續的使用者請求作好攔截的準備工作(filter物件只會建立一次,init方法也只會執行一次)。開發人員通過init方法的引數,可獲得代表當前filter配置資訊的FilterConfig物件。
- Filter物件建立之後會駐留在記憶體,一直服務。
- doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- 完成實際的過濾操作。當客戶請求訪問與過濾器關聯的URL的時候,Servlet過濾器將先執行doFilter方法。FilterChain引數用於訪問後續過濾器。
- destroy();
- 銷燬方法,只會在當web應用移除或伺服器停止時才呼叫一次來解除安裝Filter物件。
- 通常在這個方法中,可以釋放過濾器使用的資源。
FilterChain
在一個web應用當中,可以開發編寫多個Filter,這些Filter組合起來稱之為一個Filter鏈,其中每個過濾器(Filter)都可以決定是否執行下一步。
FilterChain實際上是一個介面,該介面中有一個方法:
- doFilter():。該方法被FilterChain物件呼叫,表示對Filter過濾器過濾範圍下的資源進行放行,讓鏈中下一個物件進行處理。
FilterChain在tomcat中的實現類是ApplicationFilterChain,一個ApplicationFilterChain物件包含幾個主要引數
- n => filter個數
- pos => 下一個要執行的filter的位置
- Servlet => 當pos >= n,即過濾完成時,呼叫Servlet的service方法,把請求交給Servlet
- filters => Filter的相關配置資訊
FilterChain持有所有Filter的配置資訊,它們儲存在一個數組中,然後通過移動pos,來獲取後續的Filter並執行的,這就符合之前的鏈式處理流程。
FilterConfig
與普通的 Servlet 程式一樣,Filter 也很可能需要訪問 Servlet 容器。Servlet 規範將代表 ServletContext 物件和 Filter 的配置引數資訊都封裝到一個稱為 FilterConfig 的物件中。
FilterConfig介面中有如下四個方法:
- getInitParameter():獲取初始化引數。
- getInitParameterNames():獲取所有初始化引數的名稱。
- getFilterName():獲取過濾器的配置名稱。
- getServletContext():獲取application。
使用方法
建立使用一個Filter只需要兩個步驟:
- 建立一個實現javax.servlet.Filter介面的Filter處理類實現過濾邏輯
- 配置Filter到伺服器中
Filter實現類
實現Filter介面,然後寫對應的業務程式碼即可
public class MyFilter implements Filter { public void destroy() { /*銷燬時呼叫*/ } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { /*過濾方法 主要是對request和response進行一些處理,然後交給下一個過濾器或Servlet處理*/ precode... chain.doFilter(req, resp); postcode... } public void init(FilterConfig config) throws ServletException { /*初始化方法 接收一個FilterConfig型別的引數 該引數是對Filter的一些配置*/ } }
配置方法
將Filter配置到伺服器中有兩種方法:
- 使用web.xml 配置
<filter> <filter-name>myFilter</filter-name> <filter-class>whu.web.filter.myFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
基於註解的配置
@WebFilter("/*")
一些常用配置項:
- urlPatterns:配置攔截的資源路徑
- 精確匹配 —— 如/foo.htm,只會匹配foo.htm這個URL
- 路徑匹配 —— 如/foo/*,會匹配以foo為字首的URL
- 字尾匹配 —— 如*.htm,會匹配所有以.htm為字尾的URL
- 通配——/*,會攔截所有web資源
- initParams:配置初始化引數
- initParams = { @WebInitParam(name = "key",value = "value") }
- 配置之後即可通過Filterconfig.getInitParameter("key")獲得對應value
- dispatcherTypes:配置攔截的型別,可配置多個
- REQUEST:直接訪問目標資源時執行過濾器。包括:在位址列中直接訪問、表單提交、超連結、重定向,只要在位址列中可以看到目標資源的路徑,就是REQUEST;
- FORWARD:轉發訪問執行過濾器。包括RequestDispatcher#forward()方法、< jsp:forward>標籤都是轉發訪問;
- INCLUDE:包含訪問執行過濾器。包括RequestDispatcher#include()方法、< jsp:include>標籤都是包含訪問;
- ERROR:當目標資源在web.xml中配置為< error-page>中時,並且真的出現了異常,轉發到目標資源時,會執行過濾器。
Filter執行順序
Filter的執行順序是按照FilterChain來執行的,FilterChain中Filter的順序不同配置方式下的組織情況不同,具體如下:
- 基於註解配置:按照類名的字串比較規則比較,值小的先執行
- 使用web.xml配置:根據對應的Mapping的順序組織,誰定義在上邊誰就在前
實際運用
在實際使用過程中,Filter通常有以下用途:
- 處理全站中文亂碼問題
- 過濾非法請求
- 實現自動登入
- 過濾敏感詞彙
- 壓縮網頁
- 選擇性讓瀏覽器快取
- 結合日誌記錄使用者操作