java過濾器(filter)一
Filter(過濾器)簡介:
Filter 的基本功能是對 Servlet 容器呼叫 Servlet 的過程進行攔截,從而在 Servlet 進行響應處理的前後實現一些特殊的功能。在
Servlet API 中定義了三個介面類來開供開發人員編寫 Filter 程式:Filter, FilterChain, FilterConfig。Filter 程式是一個實現了 Filter
介面的 Java 類,與 Servlet 程式相似,它由 Servlet 容器進行呼叫和執行Filter 程式需要在web.xml 檔案中進行註冊和設定它所能攔截
的資源:Filter 程式可以攔截 Jsp, Servlet, 靜態圖片檔案和靜態 html 檔案。
Filter 的基本工作原理:
當在 web.xml 中註冊了一個 Filter 來對某個 Servlet 程式進行攔截處理時,這個 Filter 就成了 Servlet 容器與該 Servlet 程式的
通訊線路上的一道關卡,該 Filter 可以對 Servlet 容器傳送給 Servlet 程式的請求和 Servlet 程式回送給 Servlet 容器的相應進行攔
截,可以決定是否將請求繼續傳遞給 Servlet 程式,以及對請求和相應資訊是否進行修改在一個 web 應用程式中可以註冊多個Filter 程
序,每個 Filter 程式都可以對一個或一組 Servlet 程式進行攔截。若有多個 Filter 程式對某個 Servlet 程式的訪問過程進行攔截,當針
對該 Servlet 的訪問請求到達時,web 容器將把這多個 Filter 程式組合成一個 Filter 鏈(過濾器鏈)。Filter 鏈中各個 Filter 的攔截順序
與它們在應用程式的 web.xml 中對映的順序一致。
Filter 介面:
init(FilterConfig filterConfig)throws ServletException:在 web 應用程式啟動時,web 伺服器將根據 web.xml 檔案中的配
置資訊來建立每個註冊的 Filter 例項物件,並將其儲存在伺服器的記憶體中。Web容器建立 Filter 物件例項後,將立即呼叫該 Filter 物件的
init 方法。Init 方法在 Filter 生命週期中僅執行一次,web 容器在呼叫 init 方法時,會傳遞一個包含 Filter 的配置和執行環境的
FilterConfig 物件(FilterConfig的用法和ServletConfig類似)。利用FilterConfig物件可以得到ServletContext物件,以及部署描述符中
配置的過濾器的初始化引數。在這個方法中,可以丟擲ServletException異常,通知容器該過濾器不能正常工作。
destroy(): 在Web容器解除安裝 Filter 物件之前被呼叫。該方法在Filter的生命週期中僅執行一次。在這個方法中,可以釋放過濾器使用
的資源。
與開發Servlet不同的是,Filter介面並沒有相應的實現類可供繼承,要開發過濾器,只能直接實現Filter介面。
doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws
java.io.IOException,ServletException:
doFilter()方法類似於Servlet介面的service()方法。當客戶端請求目標資源的時候,容器就會呼叫與這個目標資源相關聯的過濾器的
doFilter()方法。其中引數 request, response 為 web 容器或 Filter 鏈的上一個 Filter 傳遞過來的請求和相應物件;引數 chain 為代
表當前 Filter 鏈的物件,在特定的操作完成後,可以在當前 Filter 物件的 doFilter 方法內部需要呼叫 FilterChain 物件的
chain.doFilter(request,response)方法才能把請求交付給 Filter 鏈中的下一個 Filter 或者目標 Servlet 程式去處理,也可以直接向客
戶端返回響應資訊,或者利用RequestDispatcher的forward()和include()方法,以及 HttpServletResponse的sendRedirect()方法
將請求轉向到其他資源。這個方法的請求和響應引數的型別是 ServletRequest和ServletResponse,也就是說,過濾器的使用並不依賴
於具體的協議。
FilterChain 介面:
FilterChain介面:代表當前 Filter 鏈的物件。由容器實現,容器將其例項作為引數傳入過濾器物件的doFilter()方法中。過濾器物件使
用FilterChain物件呼叫過濾器鏈中的下一個過濾器,如果該過濾器是鏈中最後一個過濾器,那麼將呼叫目標資源。
doFilter(ServletRequest request,ServletResponse response)throws java.io.IOException:呼叫該方法將使過濾器鏈中的下一
個過濾器被呼叫。如果是最後一個過濾器,會呼叫目標資源。 在實現一個過濾器後,需要在 web.xml 中進行註冊和設定它所能攔截的資
源。這可以通過<filter>和<filter-mapping>元素來完成的。
其配置方式和servlet非常類似,下面是具體的配置程式碼:
/* 表示所有的url都需要被這個過濾器所過濾
在同一個 web.xml 檔案中可以為同一個 Filter 設定多個對映。若一個 Filter 鏈中多次出現了同一個 Filter 程式,這個 Filter 程式
的攔截處理過程將被多次執行。
Filter的典型應用1:使瀏覽器不快取頁面的過濾器
有 3 個 HTTP 響應頭欄位都可以禁止瀏覽器快取當前頁面,它們在 Servlet 中的示例程式碼如下:
response.setDateHeader("Expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
並不是所有的瀏覽器都能完全支援上面的三個響應頭,因此最好是同時使用上面的三個響應頭
典型應用2 :字元編碼的過濾器
通過配置引數encoding指明使用何種字元編碼,以處理Html Form請求引數的中文問題
具體的例項程式碼如下: