天天看點

Tomcat源碼閱讀之Cookie和Session

Http協定是一種無狀态協的請求/響應協定。伺服器處理來自用戶端的請求,然後向用戶端回送一條響應。Web伺服器幾乎沒有什麼資訊可以用來判斷是哪個用戶端發送的請求,也無法記錄來訪用戶端的請求序列。

Cookie的作用就是識别不同的用戶端,實作持久會話。Cookie的基本思想就是讓浏覽器持有一組伺服器特有的資訊,每次通路伺服器時都将這些資訊提供給它。

接下來我們看看Cookie是如何工作的。用戶端第一次通路Tomcat伺服器的時候,伺服器會解析Http的請求頭,由于是第一次通路,是以請求頭中并沒有能識别該用戶端的資訊,Cookie中沒有任何值。伺服器第傳回響應資訊給用戶端的時候會通過Set-Cookie或Set-Cookie2将Cookie的值添加到Http協定的頭部中。Cookie的值可以是任何資訊,通常隻包含一個伺服器為了進行跟蹤而而産生的獨特識别碼,這個識别碼就是JSESSIONID。但Cookie并不僅限于JSESSIONID,還可以以鍵/值對的方式儲存其他資訊。

Cookie可以讓伺服器跟蹤每個用戶端的通路,以差別不同的用戶端,但是每次用戶端的通路都必須傳回這些Cookie,如果Cookie很多,這無形的增加了增加了用戶端和伺服器的資料傳輸量,Session的出現正是解決這個問題。

同一個用戶端和伺服器互動時,不需要每次都傳回所有的Cookie值,隻需傳回一個ID,而這個ID就是用戶端第一次通路伺服器時産生的,并且對于每個用戶端都是唯一的。這樣用戶端就隻需傳回這個唯一的ID就行了。這個ID就是上文中提到的JSESSIONID。

那麼我們來看看Tomcat中關于Cookie和Session的這部分源碼。

Cookie的值是儲存在Http請求頭中的,是以Tomcat接收到Http請求之後會調用InternalInputBuffer類的parseHeaders解析請求頭,

由于是第一次通路,解析出來的Cookie值為空,是以Tomcat在傳回響應資訊的時候會建立Session對象和SessionId,并且将SessionId和Session對象一一關聯起來,這樣下次請求的時候就可以根據SessionId直接擷取Session對象,而不用再次建立Session對象了。建立Session的過程在ManagerBase類的createSession方法中。建立好Session對象之後接着建立Cookie對象,并将Cookie對象的name設定為JSESSIONID,value設定為SessionId對應的值。最後調用Response的addSessionCookieInternal方法将Cookie組裝成鍵/值對,并添加到響應頭中傳回給用戶端。