session management會話管理的原理
web請求與響應基于http,而http是無狀態協議。所以我們為了跨越多個請求保留用戶的狀態,需要利用某種工具幫助我們記錄與識別每一次請求及請求的其他信息。舉個栗子,我們在淘寶購物的時候,首先添加了一本《C++ primer》進入購物車,然后我們又繼續去搜索《thinking in java》,繼續添加購物車,這時購物車應該有兩本書。但如果我們不采取session management會話管理的話,基于http無狀態協議,我們在第二次向購物車發出添加請求時,他是無法知道我們第一次添加請求的信息的。所以,我們就需要session management會話管理!
會話管理的基本方式
會話管理的基本主要有隱藏域,cookies,與URL重寫這幾種實現方式。用得較多的是后兩種。
隱藏域實現會話管理
以一個網絡注冊信息填寫為例。
我們在填注冊信息的時候,經常遇到填完一個頁面的內容之后,還要繼續填寫下一個頁面的內容。但由于http的無狀態,那么容易造成的后果,當進入第二頁填寫的時候,服務器已經不記得我們上一頁填寫了什么。
怎么利用隱藏域解決這個問題呢?
顧名思義,其實就是既然服務器不會記得兩次請求間的關系,那就由瀏覽器在每次請求時主動告訴服務器多次請求間的必要信息,但是上一頁的信息并不顯示在第二頁中,而是采用隱藏域的方式。
然而顯然這種方式是存在各種問題的。
比如關掉網頁之后,就會遺失信息,而且查看網頁源代碼時,容易暴露信息,安全性不高。隱藏域并不是servlet/jsp實際會話管理的機制。
cookie實現會話管理
cookie是什么?舉個簡單的例子,現在當我們瀏覽網站的時候,經常會自動保存賬號與密碼,這樣下次訪問的時候,就可以直接登錄了。這種技術的實現就是利用了cookie技術。** cookie是存儲key-value對的一個文件,務必記住,它是由服務器將cookie添加到response里一并返回給客戶端,然后客戶端會自動把response里的cookie接收下來,并且保存到本地,下次發出請求的時候,就會把cookie附加在request里,服務器在根據request里的cookie遍歷搜索是否有與之符合的信息 **
具體cookie的實現我們會在后面詳細講到
URL重寫實現會話管理
URL重寫就是將需要記錄的信息附加在請求的鏈接背后,以鏈接參數的形式發送給服務器識別。具體實現的過程會在后文結合cookie詳解。
servlet&jsp中的session會話管理機制
** 利用httpsession對象進行會話管理。httpsession對象可以保存跨同一個客戶多個請求的會話狀態。**
換句話說,與一個特定客戶的整個會話期間看,httpsession會持久儲存。
**對于會話期間客戶做的所有請求,從中得到的所有信息都可以用httpsession對象保存。 **
httpsession的工作機制
- 以之前的問卷調查為例,當一個新客戶小明填寫問卷時,服務器會生成一個httpsession對象,用于保存會話期間小明所選擇的信息,服務器會以setAttribute的方式將其保存到httpsession對象中。
每個客戶會有一個獨立的httpsession對象,保存這個客戶所有請求所需要保存的信息。 - 服務器如何識別所有的請求是否來自同一個客戶?
客戶需要一個會話ID來標識自己。就跟我們每個人的身份證號一樣。對于客戶的第一個請求,容器會生成一個唯一的會話ID,并通過相應把它返回給用戶,客戶在以后發回一個請求中發回這個會話ID,容器看到ID之后,就會找到匹配的會話,并把這個會話與請求關聯。 - 實現存儲會話ID的就是通過cookie!
cookie存儲在客戶端,是被服務器放在response里發回客戶端的,以后每次request時,都會把cookie加入到request里。
而session是存在服務器的,以屬性的形式將會話中的信息存到httpsession對象中。調用時,只要通過httpsession對象調用相應attribute即可。
很多地方總是把session與cookie分開單獨講。但我們通過前面的介紹,不難知道,session實現其會話管理機制時,在如何確定所有請求是否來自同一個客戶時,是利用了cookie技術的。所以不應該將cookie與session完全分開講。
-
這里產生這個誤解的原因。是因為我們對session的會話管理機制不夠了解。因為容器在創建session對象時,會幫我們實現所有cookie相關的工作,而我們只需要實現這一句:
HttpSession session = request.getSession();
記住: ** 這個方法不只是創建一個會話,而是會完成所有與cookie相關的工作,只是容器都自動幫我們實現了。我們來看看容器在背后默默為我們做了什么:- 建立新的httpsession對象
- 生成唯一的會話ID
- 建立新的會話對象
- 把會話ID與cookie關聯
- 在響應中設置cookie
cookie所有的工作都在后臺進行。
看到這里,是不是很爽?容器幾乎幫我們實現了所有cookie工作。
從請求中得到會話ID
只需一行代碼:
HttpSession session = request.getSession();
與上一部分為響應生成會話ID是一致的
其中也在后臺實現了一些步驟:
if(請求包含一個會話ID)
找到與該ID匹配的會話
else if(沒有會話ID或者沒有匹配的ID)
創建一個新的會話。
還是那句話: ** cookie所有工作都在后臺自動進行 **
cookie的更多用處
cookie原先設計的初衷就是為了幫助支持會話狀態。但是因為cookie的簡便性,容器為我們封裝了大量操作。現在cookie已經被越來越運用到各個方面。
首先,** 我們明確cookie是存在客戶端的,實際上就是在客戶端與服務端交換的一小段數據(一個name/string對)。**
由于session在用戶關閉瀏覽器后,會話結束,就會消失,cookie隨之應該也會消失。但servlet的API中提供了一些方法,可以讓客戶端的cookie存活的時間更久一點。這就是cookie相對于session的一大優勢所在。我們目前常用的記住用戶名和密碼,下次登錄就是利用cookie在session消失后,還能存活實現的。
所以,我們可以定制cookie為我們實現各種功能。