實現會話跟蹤最多見的技術就是使用Session或者Cookie。而關於Session或者Cookie即簡單又複雜。簡單是由於它們自己只是 HTTP 協議中的一個配置項,在 Servlet 規範中也只是對應到一個類而已;說它複雜緣由在於當咱們的系統大到須要用到不少 Cookie 的時候,咱們不得不考慮 HTTP 協議對 Cookie 數量和大小的限制,那麼如何才能解決這個瓶頸呢? Session 也會有一樣的問題,當咱們的一個應用系統有幾百臺服務器的時候如何解決 Session 在多臺服務器之間共享?…html
Session 與 Cookie 的做用都是爲了保持訪問用戶與後端服務器的交互狀態。它們有各自的優勢,也有各自的缺陷,然而具備諷刺意味的是它們的優勢和它們的使用場景又是矛盾的。例如,使用 Cookie 來傳遞信息時,隨着 Cookie 個數的增多和訪問量的增長,它佔用的網絡帶寬也很大,試想假如 Cookie 佔用 200 個字節,若是一天的 PV 有幾億,它要佔用多少帶寬?因此有大訪問量的時候但願用 Session,可是 Session 的致命弱點是不容易在多臺服務器之間共享,因此這也限制了 Session 的使用。web
Session表明服務器與瀏覽器的一次會話過程,這個過程是連續的,也能夠時斷時續的。在Servlet中,session指的是HttpSession類的對象,這個概念到此結束了,也許會很模糊,但只有看完本文,才能真正有個深入理解。算法
一個常見的誤解是覺得session在有客戶端訪問時就被建立,然而事實是直到某server端程序調用 HttpServletRequest.getSession(true)這樣的語句時才被建立,注意若是JSP沒有顯示的使用 <% @page session=」false」%> 關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句 HttpSession session = HttpServletRequest.getSession(true);這也是JSP中隱含的 session對象的來歷。
因爲session會消耗內存資源,所以,若是不打算使用session,應該在全部的JSP中關閉它。後端
引伸:
1)、訪問*.html的靜態資源由於不會被編譯爲Servlet,也就不涉及session的問題。
2)、當JSP頁面沒有顯式禁止session的時候,在打開瀏覽器第一次請求該jsp的時候,服務器會自動爲其建立一個session,並賦予其一個sessionID,發送給客戶端的瀏覽器。之後客戶端接着請求本應用中其餘資源的時候,會自動在請求頭上添加:
Cookie:JSESSIONID=客戶端第一次拿到的session ID
這樣,服務器端在接到請求時候,就會收到session ID,並根據ID在內存中找到以前建立的session對象,提供給請求使用。這也是session使用的基本原理—-搞不懂這個,就永遠不明白session的原理。瀏覽器
session存放在哪裏:服務器端的內存中。不過session能夠經過特殊的方式作持久化管理。服務器
session的id是從哪裏來的,sessionID是如何使用的:當客戶端第一次請求session對象時候,服務器會爲客戶端建立一個 session,並將經過特殊算法算出一個session的ID,用來標識該session對象,當瀏覽器下次(session繼續有效時)請求別的資源 的時候,瀏覽器會偷偷地將sessionID放置到請求頭中,服務器接收到請求後就獲得該請求的sessionID,服務器找到該id的session返 還給請求者(Servlet)使用。一個會話只能有一個session對象,對session來講是隻認id不認人。網絡
通常來講,每次請求都會新建立一個session。
但這個也不必定的,總結下:對於多標籤的瀏覽器(好比360瀏覽器)來講,在一個瀏覽器窗口中,多個標籤同時訪問一個頁面,session是一個。對 於多個瀏覽器窗口之間,同時或者相隔很短期訪問一個頁面,session是多個的,和瀏覽器的進程有關。對於一個同一個瀏覽器窗口,直接錄入url訪問 同一應用的不一樣資源,session是同樣的。
session由於請求(request對象)而產生,同一個會話中多個request共享了一session對象,能夠直接從請求中獲取到session對象。
其實,session的建立和使用總在服務端,而瀏覽器歷來都沒獲得過session對象。但瀏覽器能夠請求Servlet(jsp也是Servlet) 來獲取session的信息。客戶端瀏覽器真正牢牢拿到的是session ID,而這個對於瀏覽器操做的人來講,是不可見的,而且用戶也無需關心本身處於哪一個會話過程當中。session
Session保存在服務器端。爲了得到更高的存取速度,服務器通常把Session放在內存裏。每一個用戶都會有一個獨立的Session。若是Session內容過於複雜,當大量客戶訪問服務器時可能會致使內存溢出。所以,Session裏的信息應該儘可能精簡。
Session在用戶第一次訪問服務器的時候自動建立。須要注意只有訪問JSP、Servlet等程序時纔會建立Session,只訪問HTML、IMAGE等靜態資源並不會建立Session。若是還沒有生成Session,也可使用request.getSession(true)強制生成Session。
Session生成後,只要用戶繼續訪問,服務器就會更新Session的最後訪問時間,並維護該Session。用戶每訪問服務器一次,不管是否讀寫Session,服務器都認爲該用戶的Session「活躍(active)」了一次。
因爲會有愈來愈多的用戶訪問服務器,所以Session也會愈來愈多。爲防止內存溢出,服務器會把長時間內沒有活躍的Session從內存刪除。這個時間就是Session的超時時間。若是超過了超時時間沒訪問過服務器,Session就自動失效了。
Session的超時時間爲maxInactiveInterval屬性,能夠經過對應的getMaxInactiveInterval()獲取,經過setMaxInactiveInterval(longinterval)修改。
Session的超時時間也能夠在web.xml中修改。另外,經過調用Session的invalidate()方法可使Session失效。jsp
雖然Session保存在服務器,對客戶端是透明的,它的正常運行仍然須要客戶端瀏覽器的支持。這是由於Session 須要使用Cookie做爲識別標誌。HTTP協議是無狀態的,Session不能依據HTTP鏈接來判斷是否爲同一客戶,所以服務器向客戶端瀏覽器發送一 個名爲JSESSIONID的Cookie,它的值爲該Session的id(也就是HttpSession.getId()的返回值)。Session 依據該Cookie來識別是否爲同一用戶。
該Cookie爲服務器自動生成的,它的maxAge屬性通常爲–1,表示僅當前瀏覽器內有效,而且各瀏覽器窗口間不共享,關閉瀏覽器就會失效。
所以同一機器的兩個瀏覽器窗口訪問服務器時,會生成兩個不一樣的Session。可是由瀏覽器窗口內的連接、腳本等打開的新窗口(也就是說不是雙擊桌面瀏覽器圖標等打開的窗口)除外。這類子窗口會共享父窗口的Cookie,所以會共享一個Session。
注意:新開的瀏覽器窗口會生成新的Session,但子窗口除外。子窗口會共用父窗口的Session。例如,在連接上右擊,在彈出的快捷菜單中選擇「在新窗口中打開」時,子窗口即可以訪問父窗口的Session。
若是客戶端瀏覽器將Cookie功能禁用,或者不支持Cookie怎麼辦?例如,絕大多數的手機瀏覽器都不支持Cookie。Java Web提供了另外一種解決方案:URL地址重寫。url