一直對Session和Cookies的使用有點困惑,趁手上有個小需求用到了的機會學習一下。
基礎知識
1.由於http協議是無狀態的協議,為了能夠記住請求的狀態,於是引入了Session和Cookie的機制。
2.Session是存在於服務器端的,在單體式應用中,由Tomcat管理,而Cookie則是存在於客户端,更方便理解的説法,可以説存在於瀏覽器。
3.Cookie只是實現Session的其中一種方案。雖然是最常用的,但並不是唯一的方法。
4.流程
- 首先,客户端會發送一個http請求到服務器端。
- 服務器端接受客户端請求後,建立一個session,併發送一個http響應到客户端,這個響應頭,其中就包含Set-Cookie頭部。該頭部包含了sessionId。
- 在客户端發起的第二次請求,假如服務器給了set-Cookie,瀏覽器會自動在請求頭中添加cookie
- 服務器接收請求,分解cookie,驗證信息,核對成功後返回response給客户端
代碼示例
1.如果沒有調用request.getSession()方法,那麼服務器永遠都不會創建JSESSIONID。
2.如果調用request.getSession()方法那麼情況分為以下兩種情況:
- 如果是第一次訪問,那麼request.getSession()會創建一個JSESSIONID,並且在響應頭裏面有設置:
Set-Cookie:JSESSIONID=********************************; Path=/; HttpOnly
- 如果不是第一訪問,那麼此次瀏覽器訪問該項目的時候,請求頭會帶有:
Cookie:JSESSIONID=*********************************
request.getSession()會先去獲取請求頭的JSESSIONID,並且在服務器裏面查找該ID,如果該session對象還存活(tomcat默認session的存活時間為30分鐘,過了30分鐘後,該session對象會被銷燬)則直接獲取該session,如果該session已經被銷燬了,則重新又創建一個session對象
分佈式情況下的Session
通過一個ngxin的負載均衡訪問來説明下存在的問題。
1.啓動一個nginx,負載均衡訪問到8080,8081兩個服務
2.首先訪問到了8080,帶回了set-cookies命令和sessionID
3.訪問getName接口,由於nginx的負載均衡,此時訪問到了8081
因為Session是存儲在了Tomcat上的,而現在是兩個Tomcat,所以Session是不同的!
整合spring-session-data-redis
首先訪問到了8080,帶回了set-cookies命令和sessionID
查看redis
訪問getName接口,由於nginx的負載均衡,此時訪問到了8081,此時沒有再生成新的sessionId
Demo: https://github.com/WillLiaowh...