1. 程式人生 > >來談一談session

來談一談session

     Session相信作為一個開發的同學並不陌生,附上百度百科的定義:Session:在計算機中,尤其是在網路應用中,稱為“會話控制”。Session 物件儲存特定使用者會話所需的屬性及配置資訊。這樣,當用戶在應用程式的 Web 頁之間跳轉時,儲存在 Session 物件中的變數將不會丟失,而是在整個使用者會話中一直存在下去。當用戶請求來自應用程式的 Web 頁時,如果該使用者還沒有會話,則 Web 伺服器將自動建立一個 Session 物件。當會話過期或被放棄後,伺服器將終止該會話。說的很好,但是好像不知所云。

    那session到底是啥呢?為何要有session呢?眾所周知,http協議是無狀態的,但是在web程式中我們一般會需要有狀態,也必須有狀態,怎麼說呢?比如我們登入了一個網站,當發起下一個請求的時候,正因為http的無狀態,我們並不知道之前登入過了,那如何讓我們知道已經登入過呢?這時候session便來了,當然還有種解決方案早已產生-cookie但cookie是儲存在客戶端的。那java web容器中對session如何實現的呢?下面以tomcat為例,來看下session實現。

  • session是如何生成的呢。

在tomcat中,StandardSession為session的標準實現類。先說下這個類最重要的一個成員變數

     這個類維護了一個map集合,一個執行緒安全的map,是不是很熟悉的名字,對就是他,當我們去setAttribute的時候實際上就是將物件加入這個map集合。當然你操作的session物件並不是他的例項,而是StandardSessionFacade他的例項,通過他維護了一個StandardSession。臥槽,是不是很熟悉,對,這就是所謂的外觀設計模式。

     現在看下session的產生,其實session的產生歸根結底是因為呼叫了request中的doGetSession方法,看下這個方法(篇幅有限省略部分程式碼):

       應用程式中的session交給了Manager去維護,manager維護了一個map集合,key就是sessionid,value便是session物件。首先通過一個requestedSessionId變數(就是要去查詢的sessionid,這個一會再說)去查詢session,找到返回,找不到則判斷create是否為true,如果是,則去建立一個session.

中間方法程式碼就不貼上了,有興趣自己點點。建立完成後,又做了什麼呢?那就是建立了一個名字為JSESSIONID 的cookie(預設情況下),然後把sessionid儲存到了cookie中。是不是很熟悉的名字。

到此session已經生成並放在cookie中,下次訪問便會帶上cookie,這一步是瀏覽器完成的。

  • Session又是何時產生的呢?

  知道了session的生成,那session又是何時產生的呢?對於這個問題,網上很多部落格之類的都再說一般開啟瀏覽器第一次訪問網站是產生,這個一般值得思考,何時不一般嗯?繼續看圖:

第一次訪問,與第二次訪問的請求與響應,可以看到第一次響應中有set-cookie欄位,有個JSESSIONID的cookie,第二次請求頭中有相同的cookie,根據之前分析,我們知道現在確實生成了session.但是看下面請求:

哎呀,並沒有哦。其實session的產生只有一種時機那便是呼叫了doGetSession,哈哈,感覺和沒說一樣,那何時呼叫呢?我們怎麼獲取的session一定記得吧,request.getSession();那我們看下這個方法:

哈哈,果真呼叫了doGetSession,而且引數為true,沒有及建立,即第一次呼叫時建立。那麼疑問來了,我開啟頁面並沒有呼叫這個方法哦。這個時候我們就要說到我們基礎知識,jsp九大內建物件,我也背不過,但是我知道一定有session,這個時候session是在小貓解析jsp的時候生成的,有圖為證,下面是解析出來的jsp,就是一個servlet

看下pagecontext中的session:

果然呼叫了getSession,懂了吧。另外會發現有個needsSession的引數,為什麼呢?那是因為jsp提供了禁止自動建立session的功能,配置<%  page  session="false"  %>

  到此明白了嗎?

  • Session的有效期

提到session失效,一定會得到這樣的答案:瀏覽器關閉。是的,session的最長生命週期就是瀏覽器開啟到關閉。說最長,起點已經瞭解,終點呢?這個都知道,session可以配置失效時間,也可以手動失效,這裡不討論這個。假定大於瀏覽器關閉時間。那為什麼關閉瀏覽器失效呢?那是因為我們生成session時,生成的放置sessionid的cookie沒有設定有效期,cookie預設有效期即瀏覽器開啟到關閉,這種cookie並沒儲存在本地,而是儲存在瀏覽器記憶體中。當cookie都沒有了,哪裡去找session?

 但,要明白一件事情,這裡的失效,並不是session物件沒有了,而是找不到他的id了,如果有之前的sessionid,依舊可以獲取session物件。這就好比,我們腦子忘記了一個人,並不是這個人沒有了,而是你忘記她的名字了呢。

  • Cookie被禁用了怎麼辦

最後一個問題,我們之前一直在說session依賴於cookie,那麼cookie被禁用了呢?你可以去做一件事情,禁用cookie,登入簡書,你會發現我擦登入不上了。難道cookie被禁用了session就完蛋了嗎?答案當然是,NO!

說到這裡,我們就要說一說之前的提到的requestedSessionId。找到tomcat中網路協議的處理類CoyoteAdapter。

其中這個方法解析一次request請求。

這便是這個變數的獲取及設定邏輯,解釋一下,sessionId依次在url,cookie,ssl請求中獲取,一個個看。

首先在路徑引數中獲取,這個引數可不是你一般理解的引數,這個是路徑後以;結尾的引數,專門處理sessionid,其他加了也沒意義。看引數名字,預設jsessionid

然後再cookie中獲取,依據的名字就不說了,和之前一樣,並設定瀏覽器cookie可用

好了,現在你大概知道cookie禁用是如何傳遞session了吧,url後面加;jsessionid=xxxxxxx,tomcat提供了url重寫的方法,當cookie可用時原路返回,不可用時,加上jsessionid引數,前提是session已經生成。

用法如:

  <a href=“<%=response.encodeRedirectURL(“index.jsp“)%>

 另外有一點很有意思,當禁用iecookie,但是訪問是用localhost的訪問,這時候瀏覽器依舊有cookie產生,但是用ip訪問就不會,別問為什麼我也不知道,要問就得問微軟0.0。我試過谷歌,火狐,IE,只有IE這樣,可以自己試下。

  • 關於http協議

   何為協議,打個比方,你與某人做生意之前,定好了12345.。等等規矩,突然有一天他沒有遵守某一規矩,我想這生意應該也沒法做了,http協議便是網路通訊雙方定的規範規矩,約定好這就是標準,如果不按約定傳送資訊,同樣也沒法通訊了。下面是我擷取到tomcat接收到及傳送的訊息,看下或許就明白了。

接收到的請求:

返回的響應:

好了,寫完了,可能大神這個都知道,但是作為像我一樣的小菜,不一定知道哦,希望能對大家能有幫助