httpSession的正確理解

 關於HttpSession的誤解實在是太多了,原本是一個很簡單的問題,怎會搞的如此的複雜呢?下面說說個人理解吧:html

一個session就是一系列某用戶和服務器間的通信。服務器有能力分辨出不一樣的用戶。一個session的創建是從一個用戶向服務器發第一個請求開始,而以用戶顯式結束或session超時爲結束。
其工做原理是這樣的:
1.當一個用戶向服務器發送第一個請求時,服務器爲其創建一個session,併爲此session建立一個標識號;
2.這個用戶隨後的全部請求都應包括這個標識號。服務器會校對這個標識號以判斷請求屬於哪一個session。
這種機制不使用IP做爲標識,是由於不少機器是經過代理服務器方式上網,無法區分每一臺機器。
對於session標識號(sessionID),有兩種方式實現:cookies和URL重寫。java

HttpSession的使用
咱們來看看在API中對session是如何定義和操做的。
當須要爲用戶端創建一個session時,servlet容器就建立了一個HttpSession對象。其中存儲了和本session相關的信息。因此,在一個servlet中有多少個不一樣用戶鏈接,就會有多少個HttpSession對象。
使用的機理是:
1.從請求中提取HttpSession對象;
2.增長或刪除HttpSession中的屬性;
3.根據須要關閉HttpSession或使其失效。web

在請求中有兩個重載的方法用來獲取HttpSession對象。
HttpSession getSession(boolean create)/getSession();做用是提取HttpSession對象,若是沒有自動建立。算法

獲取到HttpSession對象後,咱們就須要使用HttpSession的某些方法去設置和更改某些參數了。如:
void setAttribute(String name, Object value);
Object getAttribute(String name);
void removeAttribute(String name);數據庫

在javax.servlet.http包裏一共定義了四個session監聽器接口和與之關聯的兩個session事件。分別是:
HttpSessionAttributeListener and HttpSessionBindingEvent;
HttpSessionBindingListener and HttpSessionBindingEvent;
HttpSessionListener and HttpSessionEvent;
HttpSessionActivationListener and HttpSessionEvent.apache

他們的繼承關係是:
全部四個接口的父類是java.util.EventListener;
HttpSessionEvent擴展java.util.EventObject;
而HttpSessionBindingEvent又擴展了HttpSessionEvent。編程

如下分別詳述:
HttpSessionAttributeListener
當session中的屬性被添加,更改,刪除時獲得通知。這個接口上節講過,主要看其它三個。api

HttpSessionBindingListener
當一個實現了HttpSessionBindingListener的類被加入到HttpSession中(或從中移出)時,會產生HttpBindingEvent事件,而這些事件會被它自己接收到。
本接口定義了兩個方法:
void valueBound(HttpSessionBindingEvent e);
void valueUnbound(HttpSessionBindingEvent e);
當多個實現了HttpSessionBindingListener的類被加入到HttpSession中時,各種的方法只對本類感興趣,不會去理會其它類的加入。
即便是同一類的不一樣實例間,也是互不關心的(各掃門前雪)。瀏覽器

咱們能夠看到前兩個接口都對HttpSessionBindingEvent事件作出反應,但機理不一樣。
HttpSessionAttributeListener是在web.xml中登記的,servlet容器僅建立一個實例,來爲任何在session中增長屬性的servlet服務。觸發事件的對象是全部能夠轉換爲Object的實例。
HttpSessionBindingListener不用在web.xml中登記,在每一個servlet中用new建立實例,且僅對本實例向session中的加入(或移出)感興趣。觸發事件的對象僅僅是本身。tomcat

HttpSessionListener
對於session的建立和取消感興趣。須要在web.xml中登記。
共有兩個方法:
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
使用它咱們能夠容易的建立一個類來對session計數。
也許咱們會簡單的考慮使用sessionDestroyed方法來在session結束後作一些清理工做。可是,請注意,當這個方法被調用的時候,session已經結束了,你不能從中提取到任何信息了。所以,咱們要另闢蹊徑。
一種一般採用的方法是使用HttpSessionBindingListener接口。在session建立時增長一個屬性,而在session結束前最後一件事將這個屬性刪除,這樣就會觸發valueUnbound方法,全部對session的清理工做能夠在這個方法中實現。

HttpSessionActivationListener
當session在分佈式環境中跨JVM時,實現該接口的對象獲得通知。共兩個方法:
void sessionDidActivate(HttpSessionEvent se);
void sessionWillPassivate(HttpSessionEvent se);


一、HTTP協議自己是「鏈接-請求-應答-關閉鏈接」模式的,是一種無狀態協議(HTTP只是一個傳輸協議);
二、Cookie規範是爲了給HTTP增長狀態跟蹤用的(若是要精確把握,建議仔細閱讀一下相關的RFC),但不是惟一的手段;
三、所謂Session,指的是客戶端和服務端之間的一段交互過程的狀態信息(數據);這個狀態如何界定,生命期有多長,這是應用自己的事情;
四、因爲B/S計算模型中計算是在服務器端完成的,客戶端只有簡單的顯示邏輯,因此,Session數據對客戶端應該是透明的不可理解的而且應該受控於服務端;Session數據要麼保存到服務端(HttpSession),要麼在客戶端和服務端之間傳遞(Cookie或url rewritting或Hidden input);
五、因爲HTTP自己的無狀態性,服務端沒法知道客戶端相繼發來的請求是來自一個客戶的,因此,當使用服務端HttpSession存儲會話數據的時候客戶端的每一個請求都應該包含一個session的標識(sid, jsessionid 等等)來告訴服務端;
六、會話數據保存在服務端(如HttpSession)的好處是減小了HTTP請求的長度,提升了網絡傳輸效率;客戶端session信息存儲則相反;
七、客戶端Session存儲只有一個辦法:cookie(url rewritting和hidden input由於沒法作到持久化,不算,只能做爲交換session id的方式,即a method of session tracking),而服務端作法大體也是一個道理:容器有個session管理器(如tomcat的org.apache.catalina.session包裏面的類),提供session的生命週期和持久化管理並提供訪問session數據的api;
八、使用服務端仍是客戶端session存儲要看應用的實際狀況的。通常來講不要求用戶註冊登陸的公共服務系統(如google)採用cookie作客戶端session存儲(如google的用戶偏好設置),而有用戶管理的系統則使用服務端存儲。緣由很顯然:無需用戶登陸的系統惟一可以標識用戶的就是用戶的電腦,換一臺機器就不知道誰是誰了,服務端session存儲根本無論用;而有用戶管理的系統則能夠經過用戶id來管理用戶我的數據,從而提供任意複雜的個性化服務;
九、客戶端和服務端的session存儲在性能、安全性、跨站能力、編程方便性等方面都有必定的區別,並且優劣並不是絕對(譬如TheServerSide號稱不使用HttpSession,因此性能好,這很顯然:一個具備上億的訪問用戶的系統,要在服務端數據庫中檢索出用戶的偏好信息顯然是低效的,Session管理器無論用什麼數據結構和算法都要耗費大量內存和CPU時間;而用cookie,則根本不用檢索和維護session數據,服務器能夠作成無狀態的,固然高效);
十、所謂的「會話cookie」簡單的說就是沒有明確指明有效期的cookie,僅在瀏覽器當前進程生命期內有效,能夠被後繼的Set-Cookie操做清除掉。
當程序須要爲某個客戶端的請求建立一個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.
一、session在什麼時候被建立
一個常見的誤解是覺得session在有客戶端訪問時就被建立,然而事實是直到某server端程序調用 HttpServletRequest.getSession(true)這樣的語句時才被建立,注意若是JSP沒有顯示的使用 <% @page session="false"%> 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session對象的來歷。因爲session會消耗內存資源,所以,若是不打算使用session,應該在全部的JSP中關閉它。
二、存放在session中的對象必須是可序列化的嗎
不是必需的。要求對象可序列化只是爲了session可以在集羣中被複制或者可以持久保存或者在必要時server可以暫時把session交換出內存。
三、如何才能正確的應付客戶端禁止cookie的可能性
對全部的URL使用URL重寫,包括超連接,form的action,和重定向的URL,具體作法參見:
http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770
Instead, use the HttpServletResponse.encodeURL() method, for example:
out.println("<a href=/""     + response.encodeURL("myshop/catalog.jsp")      + "/">catalog</a>");
Calling the encodeURL() method determines if the URL needs to be rewritten, and if so, it rewrites it by including the session ID in the URL. The session ID is appended to the URL and begins with a semicolon.

In addition to URLs that are returned as a response to WebLogic Server, also encode URLs that send redirects. For example:
if (session.isNew()) response.sendRedirect (response.encodeRedirectUrl(welcomeURL));
四、開兩個瀏覽器窗口訪問應用程序會使用同一個session仍是不一樣的session 參見第三小節對cookie的討論,對session來講是隻認id不認人,所以不一樣的瀏覽器,不一樣的窗口打開方式以及不一樣的cookie存儲方式都會對這個問題的答案有影響。
相關文章
相關標籤/搜索