過(guò)濾器Filter學(xué)習(xí)
Filter 簡(jiǎn)介
Filter 的基本功能是對(duì) Servlet 容器調(diào)用 Servlet 的過(guò)程進(jìn)行攔截,從而在 Servlet
進(jìn)行響應(yīng)處理的前后實(shí)現(xiàn)一些特殊的功能。
在 Servlet API 中定義了三個(gè)接口類來(lái)開(kāi)供開(kāi)發(fā)人員編寫 Filter 程序:Filter, FilterChain,
FilterConfig。
Filter 程序是一個(gè)實(shí)現(xiàn)了 Filter 接口的 Java 類,與 Servlet 程序相似,它由 Servlet 容器進(jìn)行調(diào)用和執(zhí)行。
Filter 程序需要在 web.xml 文件中進(jìn)行注冊(cè)和設(shè)置它所能攔截的資源:Filter 程序可以攔截 Jsp, Servlet, 靜態(tài)圖片文件和靜態(tài)
html 文件
Filter 體系結(jié)構(gòu)
Filter并不是從真正意義上對(duì)來(lái)自客戶端的請(qǐng)求做出最終響應(yīng),而是進(jìn)行部分的過(guò)濾工作,對(duì)請(qǐng)求數(shù)據(jù)進(jìn)行檢測(cè)或者安全性檢查等工作。
Filter只有在客戶端請(qǐng)求或者發(fā)出響應(yīng)時(shí)才會(huì)自動(dòng)進(jìn)行調(diào)用,所以沒(méi)有必要把這些Filter字節(jié)嵌入到整個(gè)Web應(yīng)用系統(tǒng)的框架中,而是通過(guò)配置文件來(lái)設(shè)定。
當(dāng)然,大部分情況下,并不需要給Web應(yīng)用程序設(shè)置Filter,因?yàn)樗皇潜匦璧摹H绻枰O(shè)置Filter,除了可以設(shè)置單個(gè)Filter關(guān)聯(lián)外,還可以設(shè)置Web應(yīng)用程序與一個(gè)Filter鏈(多個(gè)單Filter相串聯(lián))相關(guān)聯(lián)。
Filter的工作過(guò)程的相關(guān)步驟:
- 首先,通過(guò)部署描述器web.xml中對(duì)Filter的配置,特定Filter會(huì)捕捉到客戶端的請(qǐng)求信息。
- Filter調(diào)用內(nèi)置方法來(lái)檢查捕獲到的請(qǐng)求對(duì)象,根據(jù)分析結(jié)果來(lái)決定是把該請(qǐng)求傳遞給下一個(gè)Filter(如果存在另一個(gè)Filter的話),還是中止該請(qǐng)求并向客戶端發(fā)出一個(gè)響應(yīng)。如果不存在Filter鏈,即僅僅為單個(gè)Filter,則上一個(gè)Filter直接把客戶請(qǐng)求轉(zhuǎn)發(fā)給Web服務(wù)器進(jìn)行相應(yīng)處理。
- 如果CSS應(yīng)用程序關(guān)聯(lián)了Filter,在客戶端請(qǐng)求設(shè)法通過(guò)各個(gè)Filter被服務(wù)器處理時(shí),最終的響應(yīng)將以相反的順序通過(guò)Filter鏈,最后發(fā)送給客戶端。
Filter 基本工作原理
當(dāng)在 web.xml 中注冊(cè)了一個(gè) Filter 來(lái)對(duì)某個(gè) Servlet 程序進(jìn)行攔截處理時(shí),這個(gè) Filter 就成了 Servlet 容器與該
Servlet 程序的通信線路上的一道關(guān)卡,該 Filter 可以對(duì) Servlet 容器發(fā)送給 Servlet 程序的請(qǐng)求和 Servlet 程序回送給
Servlet 容器相應(yīng)進(jìn)行攔截,可以決定是否將請(qǐng)求繼續(xù)傳遞給 Servlet 程序,以及對(duì)請(qǐng)求和相應(yīng)信息是否進(jìn)行修改。
在一個(gè) web 應(yīng)用程序中可以注冊(cè)多個(gè) Filter 程序,每個(gè) Filter 程序都可以對(duì)一個(gè)或一組 Servlet 程序進(jìn)行攔截。
若有多個(gè) Filter 程序?qū)δ硞€(gè) Servlet 程序的訪問(wèn)過(guò)程進(jìn)行攔截,當(dāng)針對(duì)該 Servlet 的訪問(wèn)請(qǐng)求到達(dá)時(shí),web 容器將把多個(gè) Filter
程序組合成一個(gè) Filter 鏈(過(guò)濾器鏈)。Filter 鏈中各個(gè) Filter 的攔截順序與它們?cè)趹?yīng)用程序的 web.xml 中映射的順序一致。
Filter的實(shí)現(xiàn)步驟
實(shí)現(xiàn)一個(gè)Filter的三個(gè)步驟:
- 首先編寫Filter的實(shí)現(xiàn)類程序。
- 其次,需要把實(shí)現(xiàn)的Filter添加到Web應(yīng)用程序中,也就是說(shuō),需要在Web部署描述文件Web.xml中聲明該Filter。
- 最后,將相關(guān)聯(lián)的Filter與應(yīng)用程序一起打包并部署。
Filter的主要作用及Filter API
Filter的主要作用
- 對(duì)用戶請(qǐng)求進(jìn)行統(tǒng)一認(rèn)證
- 對(duì)用戶的訪問(wèn)請(qǐng)求進(jìn)行記錄和審核
- 對(duì)用戶發(fā)送的數(shù)據(jù)進(jìn)行過(guò)濾和替換
- 轉(zhuǎn)換圖象格式
- 對(duì)響應(yīng)內(nèi)容進(jìn)行壓縮,減少傳輸量
- 對(duì)請(qǐng)求或響應(yīng)進(jìn)行加解密處理
- 觸發(fā)資源訪問(wèn)事件
- 對(duì)XML的輸出應(yīng)用XSLT
Filter API
與Filter開(kāi)發(fā)相關(guān)的接口與類都包含在javax.servlet和javax.servlet.http包中,主要有下面的接口和類。
- javax.servlet.Filter接口
- javax.servlet.FilterConfig接口
- javax.servlet.FilterChain接口
- javax.servlet.ServletRequestWrapper類
- javax.servlet.ServletResponseWrapper類
- javax.servlet.http.HttpServletRequestWrappe
r類 - javax.servlet.http.HttpServletResponseWrapp
er類
Filter接口
開(kāi)發(fā)Filter要實(shí)現(xiàn)javax.servlet.Filter接口,與開(kāi)發(fā)Servlet要實(shí)現(xiàn)javax.servlet.Servlet接口類似。提供了一個(gè)公開(kāi)的不帶參數(shù)的構(gòu)造方法。
在Filter接口中,定義了下面三個(gè)方法。
Filter接口的方法
public void init(FilterConfig filterConfig) throws
ServletException
ServletException
在 web 應(yīng)用程序啟動(dòng)時(shí),web 服務(wù)器將根據(jù) web.xml 文件中的配置信息來(lái)創(chuàng)建每個(gè)注冊(cè)的 Filter
實(shí)例對(duì)象,并將其保存在服務(wù)器的內(nèi)存中。Web容器創(chuàng)建 Filter 對(duì)象實(shí)例后,將立即調(diào)用該 Filter 對(duì)象的 init 方法。Init 方法在
Filter 生命周期中僅執(zhí)行一次,web 容器在調(diào)用 init 方法時(shí),會(huì)傳遞一個(gè)包含 Filter 的配置和運(yùn)行環(huán)境的 FilterConfig
對(duì)象(FilterConfig的用法和ServletConfig類似)。利用FilterConfig對(duì)象可以得到ServletContext對(duì)象,以及部署描述符中配置的過(guò)濾器的初始化參數(shù)。在這個(gè)方法中,可以拋出ServletException異常,通知容器該過(guò)濾器不能正常工作。
public void doFilter(ServletRequest request,ServletResponse
response,FilterChain chain) throws IOException,ServletException
response,FilterChain chain) throws IOException,ServletException
doFilter()方法類似于Servlet接口的service()方法。當(dāng)客戶端請(qǐng)求目標(biāo)資源的時(shí)候,容器就會(huì)調(diào)用與這個(gè)目標(biāo)資源相關(guān)聯(lián)的過(guò)濾器的
doFilter()方法。其中參數(shù) request, response 為 web 容器或 Filter 鏈的上一個(gè) Filter
傳遞過(guò)來(lái)的請(qǐng)求和相應(yīng)對(duì)象;參數(shù) chain 為代表當(dāng)前 Filter 鏈的對(duì)象,在特定的操作完成后,可以調(diào)用 FilterChain 對(duì)象的
chain.doFilter(request,response)方法將請(qǐng)求交付給 Filter 鏈中的下一個(gè) Filter 或者目標(biāo) Servlet
程序去處理,也可以直接向客戶端返回響應(yīng)信息,或者利用RequestDispatcher的forward()和include()方法,以及
HttpServletResponse的sendRedirect()方法將請(qǐng)求轉(zhuǎn)向到其他資源。這個(gè)方法的請(qǐng)求和響應(yīng)參數(shù)的類型是
ServletRequest和ServletResponse,也就是說(shuō),過(guò)濾器的使用并不依賴于具體的協(xié)議。
public void destroy()
Web容器調(diào)用該方法指示Filter的生命周期結(jié)束。在這個(gè)方法中,可以釋放Filter使用的資源。
與開(kāi)發(fā)Servlet不同的是,F(xiàn)ilter接口并沒(méi)有相應(yīng)的實(shí)現(xiàn)類可供繼承,要開(kāi)發(fā)過(guò)濾器,只能直接實(shí)現(xiàn)Filter接口。
FilterChain接口
代表當(dāng)前 Filter
鏈的對(duì)象,由容器實(shí)現(xiàn),容器將其實(shí)例作為參數(shù)傳入過(guò)濾器對(duì)象的doFilter()方法中。過(guò)濾器對(duì)象使用FilterChain對(duì)象調(diào)用過(guò)濾器鏈中的下一個(gè)過(guò)濾器,如果該過(guò)濾器是鏈中最后一個(gè)過(guò)濾器,那么將調(diào)用目標(biāo)資源。
FilterChain接口只有一個(gè)方法。
FilterChain接口的方法
public void doFilter(ServletRequest request,ServletResponse response)
throws IOException
throws IOException
調(diào)用該方法將使過(guò)濾器鏈中的下一個(gè)過(guò)濾器被調(diào)用。如果是最后一個(gè)過(guò)濾器,會(huì)調(diào)用目標(biāo)資源。
FilterConfig接口
javax.servlet.FilterConfig接口類似于javax.servlet.ServletConfig接口,用于在Filter初始化時(shí)向其傳遞信息。FilterConfig接口有容器實(shí)現(xiàn),容器將其作為參數(shù)傳入Filter對(duì)象的init()方法中。
在FilterConfig接口中,定義了四個(gè)方法。
FilterConfig接口的方法
public String getFilterName()
得到描述符中指定的過(guò)濾器的名字。
public String getInitParameter(String name)
返回在部署描述中指定的名字為name的初始化參數(shù)的值。如果不存在返回null。
public Enumeration getInitParameterNames()
返回過(guò)濾器的所有初始化參數(shù)的名字的枚舉集合。
public ServletContext getSerlvetContext()
返回Servlet上下文對(duì)象的引用
Filter的部署
在實(shí)現(xiàn)一個(gè)Filter后,需要在部署描述符中對(duì)Filter進(jìn)行配置,這是通過(guò)<filter>和<filter-mapping>元素來(lái)完成的。
<filter>元素
用于在Web應(yīng)用程序中聲明一個(gè)Filter。
在<filter>元素內(nèi),<description>、<display-name>、<icon>元素和以往serlvet的配置中的相同。
- <filter-name>用于為Filter指定一個(gè)名稱,該元素的內(nèi)容不能為空。
- <filter-class>元素用于指定Filter的完整的限定類名。
- <init-param>元素用于為Filter指定初始化參數(shù)。它的子元素<param-name>指定參數(shù)的名稱;<param-value>指定參數(shù)的值。
在Filter中,可以使用FilterConfig接口對(duì)象來(lái)訪問(wèn)初始化參數(shù)。
<filter-mapping>元素
用于指定Filter關(guān)聯(lián)的url樣式或者Servlet。
- <filter-name>子元素的值必須是在<filter>元素中聲明過(guò)的Filter的名字。
- <url-pattern>元素指定Filter關(guān)聯(lián)的URL樣式。
- <servlet-name>元素指定Filter對(duì)應(yīng)的Servlet。
<url-pattern>元素和<servlet-name>元素可以選擇一個(gè);用戶在訪問(wèn)<url-pattern>元素指定的URL上的資源或<servlet-name>元素指定的Servlet時(shí),該Filter才會(huì)被容器調(diào)用。
-------------------------------
Filter演示示例
創(chuàng)建一個(gè)簡(jiǎn)單的Filter(TimeTrackFilter.java),跟蹤滿足一個(gè)客戶機(jī)的Web請(qǐng)求大致所花的時(shí)間。
創(chuàng)建Filter
TimeTrackFilter.java
package cn.jbit.auction.servlet; import java.io.IOException; import java.util.Date; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class TimeTrackFilter implementsFilter
{ private FilterConfig filterConfig = null; // 初始化Filterpublic void init(FilterConfig filterConfig) throws ServletException
{ // TODO Auto-generated method stub this.filterConfig = filterConfig; } // 執(zhí)行Filter功能public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{ // TODO Auto-generated method stub Date startTime,endTime; double totalTime; startTime = new Date(); // 把處理發(fā)送到下一個(gè)Filter chain.doFilter(request, response); // 接下來(lái)的語(yǔ)句就是處理請(qǐng)求的過(guò)程:計(jì)算開(kāi)始到結(jié)束的時(shí)間 endTime = new Date(); totalTime = endTime.getTime()-startTime.getTime(); totalTime = totalTime / 1000; System.out.println("============================="); System.out.println("Total elapsed time is: " + totalTime + " seconds."); System.out.println("============================="); filterConfig.getServletContext(); }public void destroy()
{ // TODO Auto-generated method stub this.filterConfig = null; } }
配置Filter
實(shí)現(xiàn)了Filter后,還需要通過(guò)web.xml文件中的兩上XML元素來(lái)聲明該Filter。
配置web.xml
<filter> <filter-name>requestTimer
</filter-name> <filter-class>cn.jbit.auction.servlet.TimeTrackFilter
</filter-class> </filter> <filter-mapping> <filter-name>requestTimer
</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
posted on 2012-04-22 15:56 hantai 閱讀(140) 評(píng)論(0) 編輯 收藏