Servlet2.3中文文檔(第6,7章)
第六章
6 Filtering
Fileter是servlet2.3新增的部分。這一章介紹Filter類和方法,以及在web工程中的配置。
6.1什么是Fileter
Filter是重復(fù)使用的,用于變換HTTP請(qǐng)求和響應(yīng)以及頭信息中的內(nèi)容。Filter不能像servlet那樣創(chuàng)建
response響應(yīng),但可以修改請(qǐng)求和響應(yīng)的內(nèi)容。
6.1.1例舉一些Filter
驗(yàn)證Filter
登陸,審核Filter
圖像處理Filter
數(shù)據(jù)壓縮Filter
加密Filter
XSL/T Filter
MIME Filter
6.2 主要觀念
開(kāi)發(fā)者通過(guò)創(chuàng)建實(shí)現(xiàn)javax.servlet.Filter接口的類,并提供一個(gè)沒(méi)有參數(shù)的構(gòu)造函數(shù)來(lái)創(chuàng)建一個(gè)Filter。
在描述文件中Fileter用filter表示,調(diào)用方法用filter-mapping進(jìn)行配置。
6.3 Filter生命周期
在web工程發(fā)布后,在請(qǐng)求使引擎訪問(wèn)一個(gè)web資源之前,引擎必須定位Filter列表;引擎必須確保為列
表中的每一個(gè)Filter建立了一個(gè)實(shí)例,并調(diào)用了他們的init(FilterConfig config)方法。在這過(guò)程中可以拋
出異常。
部署描述文件中定義的所有filter,僅會(huì)在引擎中產(chǎn)生一個(gè)實(shí)例。
引擎為filter提供了一個(gè)FilterConfig類,該類附有ServletContext和一個(gè)帶有初始化參數(shù)的set。
當(dāng)引擎接受一個(gè)請(qǐng)求時(shí),引擎就會(huì)調(diào)用filter列表中第一個(gè)filter的doFilter方法,把ServletRequest,
ServletResponse和FilterChain作為參數(shù)傳給它。
filter中doFilter方法典型的處理步驟是:
1)檢查請(qǐng)求頭信息
2)開(kāi)發(fā)者創(chuàng)建一個(gè)實(shí)現(xiàn)了ServletRequest或HttpServletRequest的類,去包裝request對(duì)象,以
便修改請(qǐng)求的頭信息或體數(shù)據(jù)。
3)開(kāi)發(fā)者創(chuàng)建一個(gè)實(shí)現(xiàn)了ServletReqponse或HttpServletResponse的類,去包裝response對(duì)
象,以便修改請(qǐng)求的頭信息或體數(shù)據(jù)。
4)filter可以調(diào)用鏈中的下一個(gè)實(shí)體,下一個(gè)實(shí)體是另一個(gè)filter,如果該filter是列表中最后的一
個(gè),則它的下一個(gè)實(shí)體就是一個(gè)目標(biāo)web資源。如果要調(diào)用下一個(gè)filter的doFilter方法,把
request,和response對(duì)象傳給FilterChain對(duì)象的doFilter方法中就可以了。
Filter chain 的doFilter方法是由引擎提供的,引擎在該方法中會(huì)定位filter列表中的下一個(gè)filter,
調(diào)用它的doFilter方法,把傳來(lái)的request和response對(duì)象傳給它。
5)在調(diào)用chain.doFilter之后,filter可以檢測(cè)響應(yīng)的頭信息
6)在這些過(guò)程中,filter可以拋出異常。當(dāng)在調(diào)用doFilter過(guò)程中拋出UnavailableException異常
時(shí),引擎重復(fù)嘗試處理下面的filter chain的方法,如過(guò)時(shí)后還沒(méi)請(qǐng)求到filter chain 就會(huì)關(guān)閉對(duì)
filter chain的請(qǐng)求。
當(dāng)filter是列表中最后一個(gè)filter時(shí),它的下一個(gè)實(shí)體是描述配置文件中filter后面的servlet或其它
資源。
在引擎刪除一個(gè)Filter之前,引擎必須調(diào)用Filter的destroy方法,來(lái)釋放資源。
6.3.1 包裝Requests 和Responsees
過(guò)濾的中心觀念是對(duì)request或response的包裝,在這種模式下,開(kāi)發(fā)者不僅可以改寫(xiě)存在的方法,還
可以創(chuàng)建自己的新方法,用于特殊的過(guò)濾任務(wù),例如:開(kāi)發(fā)者希望擴(kuò)展response對(duì)象,希望有個(gè)更高層
次的輸出流對(duì)象(writer)。
為了支持包裝模式,引擎不許保證在整個(gè)過(guò)濾鏈中,傳遞的request和response對(duì)象都是同一個(gè)對(duì)象。
6.3.2 Filter的環(huán)境
Filter的初始參數(shù)可以在描述配置文件中用init-params元素來(lái)配置,在運(yùn)行時(shí)中,用FilterConfig的
getInitParameter和getInitParamesterNames方法得到配置參數(shù)。
6.3.3 Filter在web工程中的配置
在部署描述文件中:
filter-name:filter名稱
filter-class:filter類路徑
init-params:用于初始化參數(shù)
如果開(kāi)發(fā)者在部署描述中為一個(gè)filter類描述了兩個(gè)定義,則引擎會(huì)創(chuàng)建這個(gè)filter類的兩個(gè)實(shí)例。
下面是個(gè)配置的例子:
<filter>
<filter-name>Image Filter</filter-name>
<filter-class>com.acme.ImageServlet</fiflter-class>
</filter>
一旦filter在部署描述中定義,filter-mapping就可以被定義了,filter-mapping在web應(yīng)用中是定義關(guān)聯(lián)
filter的servlet和靜態(tài)資源的。
如:
<filter-mapping>
<filter-name>Image Filter</filter-name>
<servlet-name>ImageServlet</servlet-name>
</filter-mapping>
Image Filter 的 Filter就和ImageServlet 的Servlet建立了關(guān)聯(lián)。
Filter 可以和一群servlet和靜態(tài)資源關(guān)聯(lián),用url-pattern。如:
<filter-mapping>
<filter-name>Loging Filter</filter-name>
<url-pattern>/*</url-pattern>
<filter-mapping>
引擎建立特殊請(qǐng)求URI的Filter鏈的順序是:
1)url-pattern映射fiter-mapping的順序和描述文件中定義的順序是一樣的。
2)servlet-name映射filter-mapping的順序和描述文件中定義的順序是一樣的。
這種需求要求引擎在接受請(qǐng)求時(shí):
.識(shí)別符合SRV.11.2規(guī)則的web資源。
.如果一些filter是servlet和有servlet-name的web資源匹配的,引擎就會(huì)創(chuàng)建一個(gè)和描述文件中
映射servlet-name的順序一樣的filter鏈。
.如果一些filter是rul-pattern關(guān)聯(lián)的,引擎就會(huì)創(chuàng)建一個(gè)和描述文件中映射url-pattern的順序一
樣的efilter鏈。
一個(gè)高性能的web容器將會(huì)緩存filter鏈。
第七章 Sessions
超文本傳輸協(xié)議(HTTP)是無(wú)狀態(tài)的協(xié)議。要建立一個(gè)有效的web應(yīng)用,客戶端之間的通信是需要
的。有很多會(huì)話跟蹤的策略,
但是直接使用這些技術(shù)都很難使用。servlet規(guī)范中提供了一個(gè)簡(jiǎn)單的HttpSession接口,不需要開(kāi)發(fā)者
關(guān)心會(huì)話跟蹤的具體細(xì)節(jié)。
7.1 會(huì)話跟蹤機(jī)制
下面描述了幾種會(huì)話的跟蹤機(jī)制
7.1.1 Cookies
HTTP cookies是最常用的會(huì)話跟蹤機(jī)制,所有的servlet引擎都應(yīng)該支持這種方法。
引擎發(fā)送一個(gè)cookie到客戶端,客戶端就會(huì)在以后的請(qǐng)求中把這個(gè)cookie返回給服務(wù)器。用戶會(huì)話跟蹤
的cookie的名字必須是JSESSIONID
7.1.2 SSL Sessions
在安全套接字層,加密技術(shù)用在了HTTPS協(xié)議,從一個(gè)客戶端來(lái)的多個(gè)請(qǐng)求允許用一個(gè)含糊的標(biāo)識(shí),
servlet引擎就用這個(gè)數(shù)據(jù)定義一個(gè)Session。
7.1.3 URL重寫(xiě)
URL重寫(xiě)是最低性能的通用會(huì)話跟蹤方法。當(dāng)一個(gè)客戶端不能接受cookie時(shí),URL重寫(xiě)就會(huì)作為基本的
會(huì)話跟蹤方法;URL重寫(xiě)包括一個(gè)附加的數(shù)據(jù),一個(gè)session id,這樣的URL會(huì)被引擎解析和一個(gè)session
相關(guān)聯(lián)。一個(gè)session id是作為URL的一個(gè)被編碼的參數(shù)傳輸?shù)模@個(gè)參數(shù)名字必須是jsessionid.如下面
的例子:
http://www.myserver.com/catalog/index.html;jsessionid=1234
7.1.4 會(huì)話的完整性
一個(gè)web容器必須支持HTTP 會(huì)話。而當(dāng)cookies方法不被支持時(shí),通常使用URL重寫(xiě)方法。
7.2 創(chuàng)建一個(gè)會(huì)話
servlet設(shè)計(jì)者必須考慮到一個(gè)客戶端不能加入session的情況。
7.3 會(huì)話范圍
HttpSession對(duì)象只在應(yīng)用程序級(jí)有效,通常用于session的cookie可以服務(wù)于不同的上下文,但一個(gè)
HttpSession實(shí)例只服務(wù)于一個(gè)會(huì)話。舉個(gè)例子:如一個(gè)servlet A用RequestDispatcher去調(diào)用另一個(gè)web
應(yīng)用中的另一個(gè)servlet B,用于A和B的會(huì)話一定是兩個(gè)不同的會(huì)話。
7.4 Session屬性的邦定
一個(gè)servlet可以通過(guò)一個(gè)name邦定一個(gè)對(duì)象到HttpSession實(shí)例中;只要獲得包含同一個(gè)會(huì)話的請(qǐng)求對(duì)
象,任何邦定到會(huì)話中的對(duì)象在同一個(gè)ServletContext中對(duì)于其它的servlet都是可用的。
當(dāng)把一個(gè)對(duì)象放入session或從session刪除時(shí)可能要通知其它對(duì)象,這些信息能夠被實(shí)現(xiàn)了
HttpSessionBindingListener接口的對(duì)象獲得,這個(gè)接口定義了一下的一些方法。
valueBound
valueUnbound
valueBound方法在HttpSession接口調(diào)用getAttribute方法獲得一個(gè)有效的對(duì)象之前調(diào)用。valueUnbound
方法在HttpSession接口調(diào)用getAttribute方法獲得一個(gè)不再有效的對(duì)象后調(diào)用。
7.5 會(huì)話超時(shí)
在HTTP協(xié)議中,當(dāng)客戶端不再有效時(shí),沒(méi)有清楚的定義終止信號(hào)。這就意味著通常只能采用時(shí)間超時(shí)
來(lái)表明客戶端不再有效。
默認(rèn)的超時(shí)時(shí)間是servlet引擎定義的,通過(guò)HttpSession的getMaxInactiveInterval方法可以得到超時(shí)的
時(shí)間;開(kāi)發(fā)者可用用setMaxInactiveInterval方法來(lái)設(shè)置超時(shí)的時(shí)間,以秒定義的。如果一個(gè)session的
超時(shí)時(shí)間被設(shè)置為-1,則這個(gè)session將永遠(yuǎn)有效。
7.6 最后訪問(wèn)時(shí)間
在當(dāng)前的請(qǐng)求中用HttpSession接口的getLastAccessedTime可以獲得最后一次訪問(wèn)session的時(shí)間。
7.7 重要session
7.7.1 線程問(wèn)題
在一個(gè)可以配置的應(yīng)用中,所有的請(qǐng)求都是一個(gè)會(huì)話的一部分,引擎一定能夠取出通過(guò)setAttribute或
putValue放入HttpSession對(duì)象中的對(duì)象。注意以下的情況:
.引擎一定能夠訪問(wèn)實(shí)現(xiàn)了Serializable接口的對(duì)象。
.引擎可以選擇存儲(chǔ)HttpSession對(duì)象中指定的對(duì)象,如EJB組件和事務(wù)。
.引擎能夠監(jiān)聽(tīng)到會(huì)話的變動(dòng)。
如果放入session中的對(duì)象沒(méi)有被Seializable或沒(méi)有效,servlet可以拋出IllegalArgumentException;如果
引擎不支持Session存儲(chǔ)對(duì)象的機(jī)制,引擎一定會(huì)拋出IllegalArgumentException。
這些限制意味著,在一個(gè)分布式引擎中,不會(huì)有額外的并發(fā)問(wèn)題。
如果引擎為了service的品質(zhì)持續(xù)化或遷移session,使用本地持續(xù)化的HttpSession或它的屬性是不受限
制的,開(kāi)發(fā)者要想確保放入session中的屬性對(duì)象能夠可用,最好對(duì)象實(shí)現(xiàn)Serializable接口。
在遷移一個(gè)session時(shí)引擎必須通知session中實(shí)現(xiàn)了HttpSessinActivationListener的屬性對(duì)象,必須通知
在序列化前鈍化的或序列化后激活的session的監(jiān)聽(tīng)器。
開(kāi)發(fā)分布式的開(kāi)發(fā)者應(yīng)該清楚的是,一旦引擎運(yùn)行在超過(guò)一個(gè)JVM的時(shí)候,就不能用static 表明變量來(lái)
存儲(chǔ)應(yīng)用狀態(tài),應(yīng)該用EJB或數(shù)據(jù)庫(kù)賴存儲(chǔ)。
7.7.3客戶端
因?yàn)閏ookies或SSL證書(shū)都是被web瀏覽器訪問(wèn)過(guò)程控制的,與任何特殊的window瀏覽器是沒(méi)有關(guān)系的。
所以從所有window客戶端到一個(gè)servlet引擎的請(qǐng)求是同一個(gè)會(huì)話的一部分。最好是開(kāi)發(fā)者總是設(shè)想所
有的window客戶端是一起參與同一個(gè)會(huì)話的。
posted on 2007-08-20 17:35 朱巖 閱讀(292) 評(píng)論(0) 編輯 收藏 所屬分類: servlet文章