Servlet容器的會話跟蹤
HTTP協(xié)議是一種無狀態(tài)的協(xié)議,而對于現(xiàn)在的web應用而言,我們往往需要記錄從特定客戶端的一系列請求間的聯(lián)系?,F(xiàn)在已經(jīng)有很多會話跟蹤的技術,但是對于程序員而言都不是很方便直接使用。Servlet規(guī)范定義了一個簡單的HttpSession接口以方便Servlet容器進行會話跟蹤而不需要開發(fā)者注意實現(xiàn)的細節(jié)。一般而言,有兩種最常用的會話跟蹤機制,一種就是URL重寫。在客戶端不接受cookie的情況下可以使用URL重寫進行會話跟蹤。
URL重寫包括向URL路徑添加一些容器可以解釋的數(shù)據(jù)。規(guī)范要求會話ID必須編碼在URL路徑中,參數(shù)名稱必須是jsessionid,例如: http://www.myserver.com/catalog/index.html;jsessionid=1234,另一種就是現(xiàn)在最常用的cookie了,規(guī)范要求所有的Servlet都必須支持cookie。容器向客戶端發(fā)送一個cookie,客戶端在后續(xù)的處于同一個會話的請求中向服務器返回該cookie。會話跟蹤cookie的名字必須是JSESSIONID。
新出現(xiàn)的一種會話功能是SSL會話,SSL(Secure Sockets Layer,安全套接字層)是HTTPS協(xié)議使用的一種加密技術,內(nèi)建了會話跟蹤功能,Servlet容器可以非常容易的使用這些數(shù)據(jù)建立會話跟蹤。(但是HTTPS不是規(guī)范要求Servlet必須支持的協(xié)議) 因為HTTP是一種基于請求響應的協(xié)議,因此會話只有在客戶端加入它以后才被新建立。當會話跟蹤信息被成功的返回給服務器以指示會話給建立時客戶端才算加入了一個會話。如果客戶端沒有加入會話,那么下一次請求不會被認為是會話的一部分。如何客戶端還不知道會話或者客戶端選擇不加入一個會話,那么會話被認為是新的。開發(fā)者必須自己設計自己的應用中的會話處理狀態(tài),在什么地方?jīng)]有加入會話,什么地方不能加入會話以及什么地方不需要加入會話。
規(guī)范要求HttpSession在應用或者Servlet上下文級別有效,諸如cookie這樣的建立會話的底層機制可以在上下文中共享,但是對于那些外露的對象,以及更重要的是對象的那些屬性是不能在上下文中共享的。對于會話的屬性的綁定而言,任何對象都可以綁定到某個命名屬性。被綁定的屬性對象對于其它處于相同ServletContext并且處于同一個會話處理中的其它Servlet也是可見的。
某些對象在被加入會話或者被從會話中移除時要求得到通知,這樣的信息可以通過讓該對象實現(xiàn)HttpSessionBindingListener接口得到。該接口定義了兩個方法用以標記被綁定到會話或者從會話中被移除。 valueBound方法在對象通過getAttribute之前就被調(diào)用,而valueUnbound方法在對象已經(jīng)不能通過getAttribute得到后才被調(diào)用。
由于HTTP是無狀態(tài)協(xié)議,因此客戶端不再活動時沒有什么明顯的信號,這也就意味著只有一種機制可以用于表明客戶端不再活動:超時。會話的缺省的時限由Servlet容器定義并且可以通過HttpSession的getMaxInactiveInterval得到,開發(fā)者也可以通過使用setMaxInactiveInterval
方法進行設置,這些方法返回的單位是秒,如果時限被設置為-1,那么意味著永遠不會超時。通過調(diào)用HttpSession的getLastAccessedTime方法,我們可以得到在當前請求之前的訪問時間。當會話中的一個請求被Servlet上下文處理時會話就被認為被訪問了。
另外需要注意的就是一些很重要的會話的語義問題。
◆多線程問題:多個請求線程可能會同時訪問同一個會話,開發(fā)者有責任以適當?shù)姆绞酵皆L問會話中的資源。
◆分布式環(huán)境:對于被標記為可分布的應用而言,同一會話中的所有請求只能被單一的VM處理。同時,放入HttpSession中的所有對象都必須實現(xiàn) Serializable接口,否則容器可能會拋出IllegalArgumentException(在jboss_tomcat下沒有拋出這個異常,但是如果在關閉服務器時還有未完成的會話,那么服務器在試圖存儲會話時會出現(xiàn)串行化異常,在重新啟動的時候會試圖回復會話,也會出現(xiàn)異常)。
這個限制意味著開發(fā)者不會遇到非可分布容器中的那些并發(fā)問題。另外容器提供者可以通過將一個會話對象以及它的內(nèi)容從分布式系統(tǒng)的一個活動節(jié)點移動到系統(tǒng)的其它不同節(jié)點的能力來保證可伸縮性。
◆客戶端的語義:基于cookie或者SSL證書通常是被web瀏覽器控制并且不聯(lián)系到特定瀏覽器窗口的事實,從客戶端應用的所有窗口發(fā)送到容器的請求都可能是同一個會話。為了達到最大的可移植性,開發(fā)者不能總假設特定客戶端的所有窗口的請求都處于同一個會話中。
【編輯推薦】