看了一些Session的資料,在這裡再總結一下Session相關的知識(很多是從網上搜集的資料)。
<b>1.Session是什麼?</b>
session,中文經常翻譯為會話。
(1).打個比方:比如打電話時從拿起電話撥号到挂斷電話這中間的一系列過程可以稱之為一個session。同理,使用者的一次Session可以了解為:打開這個網站到關閉這個網站的一系列動作。
(2).然而當session一詞與網絡協定相關聯時,它又往往隐含了“面向連接配接”和/或“保持狀态”這樣兩個含義,“面向連接配接”指的是在通信雙方在通信之前要先建立一個通信的管道,比如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你并不能确認對方的位址是否正确,通信管道不一定能建立,但對發信人來說,通信已經開始了。“保持狀态”則是指通信的一方能夠把一系列的消息關聯起來,使得消息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客并且記得上次這個顧客還欠店裡一塊錢。這一類的例子有“一個TCP session”或者“一個POP3 session”。
(3).而到了web伺服器蓬勃發展的時代,session在web開發語境下的語義又有了新的擴充,它的含義是指一類用來在用戶端與伺服器之間保持狀态的解決方案。有時候session也用來指這種解決方案的存儲結構,如“把xxx儲存在session裡”。
(4).由于各種用于web開發的語言在一定程度上都提供了對這種解決方案的支援,是以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經常把Java裡提供的javax.servlet.http.HttpSession簡稱為session。
<b>2.為什麼需要Session?</b>
<b>3.了解Session機制</b>
session機制是一種伺服器端的機制,伺服器使用一種類似于散清單的結構來儲存資訊。
當程式需要為某個用戶端的請求建立一個session的時候,伺服器首先檢查這個用戶端的請求裡是否已包含了一個session辨別 - 稱為session id,如果已包含一個session id則說明以前已經為此用戶端建立過session,伺服器就按照session id把這個session檢索出來使用(如果檢索不到,可能會建立一個),如果用戶端請求不包含session id,則為此用戶端建立一個session并且生成一個與此session相關聯的session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字元串,這個session id将被在本次響應中傳回給用戶端儲存。
儲存這個session id的方式可以采用cookie,這樣在互動過程中浏覽器可以自動的按照規則把這個辨別發揮給伺服器。一般這個cookie的名字都是類似于 SEEESIONID,而。比如weblogic對于web應用程式生成的cookie,JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是JSESSIONID。
由于cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session id傳遞回伺服器。經常被使用的一種技術叫做URL重寫,就是把session id直接附加在URL路徑的後面,附加方式也有兩種,一種是作為URL路徑的附加資訊,表現形式為http://...../xxx;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
另一種是作為查詢字元串附加在URL後面,表現形式為http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
這兩種方式對于使用者來說是沒有差別的,隻是伺服器在解析的時候處理的方式不同,采用第一種方式也有利于把session id的資訊和正常程式參數區分開來。為了在整個互動過程中始終保持狀态,就必須在每個用戶端可能請求的路徑後面都包含這個session id。
另一種技術叫做表單隐藏字段。就是伺服器會自動修改表單,添加一個隐藏字段,以便在表單送出時能夠把session id傳遞回伺服器。比如下面的表單
<a></a>
<form name="testform" action="/xxx">
<input type="text">
</form>
在被傳遞給用戶端之前将被改寫成
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
這種技術現在已較少應用,筆者接觸過的很古老的iPlanet6(SunONE應用伺服器的前身)就使用了這種技術。實際上這種技術可以簡單的用對action應用URL重寫來代替。
在談論session機制的時候,常常聽到這樣一種誤解“隻要關閉浏覽器,session就消失了”。其實可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易删除顧客的資料。對session來說也是一樣的,除非程式通知伺服器删除一個session,否則伺服器會一直保留,程式一般都是在使用者做log off的時候發個指令去删除session。然而浏覽器從來不會主動在關閉之前通知伺服器它将要關閉,是以伺服器根本不會有機會知道浏覽器已經關閉,之是以會有這種錯覺,是大部分session機制都使用會話cookie來儲存session id,而關閉浏覽器後這個session id就消失了,再次連接配接伺服器時也就無法找到原來的session。如果伺服器設定的cookie被儲存到硬碟上,或者使用某種手段改寫浏覽器發出的 HTTP請求頭,把原來的session id發送給伺服器,則再次打開浏覽器仍然能夠找到原來的session。
恰恰是由于關閉浏覽器不會導緻session被删除,迫使伺服器為seesion設定了一個失效時間,當距離用戶端上一次使用session的時間超過這個失效時間時,伺服器就可以認為用戶端已經停止了活動,才會把session删除以節省存儲空間。
<b>4.HTTPSession中的一些細點:</b>
(1)、session在何時被建立
一個常見的誤解是以為session在有用戶端通路時就被建立,然而事實是直到某server端程式調用 HttpServletRequest.getSession(true)這樣的語句時才被建立,注意如果JSP沒有顯示的使用 <%@page session="false"%> 關閉session,則JSP檔案在編譯成Servlet時将會自動加上這樣一條語句HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隐含的session對象的來曆。
由于session會消耗記憶體資源,是以,如果不打算使用session,應該在所有的JSP中關閉它。
(2)、session何時被删除
綜合前面的讨論,session在下列情況下被删除a.程式調用HttpSession.invalidate();或b.距離上一次收到用戶端發送的session id時間間隔超過了session的逾時設定;或c.伺服器程序被停止(非持久session)
(3)、如何做到在浏覽器關閉時删除session
嚴格的講,做不到這一點。可以做一點努力的辦法是在所有的用戶端頁面裡使用javascript代碼window.oncolose來監視浏覽器的關閉動作,然後向伺服器發送一個請求來删除session。但是對于浏覽器崩潰或者強行殺死程序這些非正常手段仍然無能為力。
(4)、存放在session中的對象必須是可序列化的嗎
不是必需的。要求對象可序列化隻是為了session能夠在叢集中被複制或者能夠持久儲存或者在必要時server能夠暫時把session交換出記憶體。在Weblogic Server的session中放置一個不可序列化的對象在控制台上會收到一個警告。我所用過的某個iPlanet版本如果session中有不可序列化的對象,在session銷毀時會有一個Exception,很奇怪。
(5)、如何才能正确的應付用戶端禁止cookie的可能性
對所有的URL使用URL重寫,包括超連結,form的action,和重定向的URL。相關資料可查詢:http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
(6)、開兩個浏覽器視窗通路應用程式會使用同一個session還是不同的session
對session來說是隻認id不認人,是以不同的浏覽器,不同的視窗打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。
先總結這些,有機會再補充。
<b>5.參考資料:</b>
(1).http://zhidao.baidu.com/question/2601861.html
(2).http://baike.baidu.com/view/25258.htm
本文轉自hyddd部落格園部落格,原文連結:http://www.cnblogs.com/hyddd/archive/2008/12/29/1364646.html,如需轉載請自行聯系原作者。