Session的底层实现原理
生活随笔
收集整理的這篇文章主要介紹了
Session的底层实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Session實現原理
客戶對向服務器端發送請求后,Session 創建在服務器端,返回Sessionid給客戶端瀏覽器保存在本地,
當下次發送請求的時候,在請求頭中傳遞sessionId獲取對應的從服務器上獲取對應的SesisonSession常見問題
Session 保證在那里?
答案:存放在服務器上
關閉瀏覽器Session會失效嗎
答案:不會消失
?
我們開始分析SESSION的一個原理,這是要重點的去給大家講的,SESSION的原理,我們在講SESSION原理的時候要快一點,localhost:8080/createSession?nameValue=zhangsan http://localhost:8080/getSessionSESSION常見的問題,瀏覽器關閉了SESSION,SESSION會失效嗎,這個是為空的,既然是為空的,在這里我們做一件事,localhost:8080/createSession?nameValue=leon644,這個時候我們是不是可以把值存放進去了,這個時候我們再查一下,http://localhost:8080/getSession, 8080-leon644,是不是查得到,這個是屬于一個非常基礎的知識,瀏覽器關閉session會失效嗎,這是第一個問題,第二個問題是SESSION存放在哪里,有沒有人能告訴我答案的,SESSION肯定是存放在服務器端上的,瀏覽器關閉SESSION,SESSION會失效嗎,肯定不會失效的,為什么呢,這是我要重點去講的,在這個地方我去給大家畫一個圖,畫一個什么圖呢,在這個地方我們寫一下,叫做客戶端,我們舉一反三,然后把它去copy一遍,是不是叫做服務器端的,這個地方我們叫做服務器端,你們要記住,我們發起http請求的話,客戶端和服務器端要進行通信的時候,在這個時候大家一定要思考一下,走的是請求,英文叫做request,那么舉一反三,如果服務器端響應給客戶端的時候,這個時候我們叫做response,這個你們肯定都知道,response的英文怎么說,我們叫做響應,響應的過程我們叫做response,那么這個地方你們肯定就知道了,本身來說一個HTTP通信的話,http通訊本身就是基于請求和響應的過程,既然他基于請求和響應的話,這個時候客戶端我們可以理解為瀏覽器,這個地方大家去看,你們看代碼Cookie: JSESSIONID=66115D0AA6ACFCF82AA61999799F571A存入Session sessionid:信息66115D0AA6ACFCF82AA61999799F571A,nameValue:zhangsan,serverPort:8080這個時候本地是會把SESSIONID保存起來,這表示什么意思呢,http://localhost:8080/createSession?nameValue=zhangsan這是第一次請求,也就是什么意思,也就是客戶端向服務器端發起createSession請求的時候,創建session,返回sessionId打開開發者工具里面,當你再去查詢的時候,客戶端是不是會讀取到本地的sessionId,存放到請求頭里面去,是不是能夠查到這個值,在請求頭里面是不是有sessionId,客戶端它會讀取到本地的sessionId,然后存放到請求頭里面去,他這邊是不是就查對應的結果,你們有沒有發現一個問題,為什么響應頭里面沒有顯示全,createSession的時候響應頭里面為什么沒有sessionId,但是請求頭里面有sessionId,這是什么原因,你們不覺得不對勁嗎,客戶端發起一個createSession請求的時候,通過響應頭把sessionId響應給客戶端,響應頭里面沒有返回sessionId給客戶端,但是請求頭里面有,這是什么原因,是因為你第一次創建完了之后,Set-Cookie: JSESSIONID=A8E197E167C7750BB9D19D1B8F420B5B; Path=/; HttpOnlyCookie: JSESSIONID=66115D0AA6ACFCF82AA61999799F571A讀取緩存中的,在這邊你們把緩存全部清掉看,因為它已經有了,清除緩存,他是不是會把本地的sessionId全部給清除掉,這個之后,是不是返回來sessionId看到沒有,Set-Cookie: JSESSIONID=A8E197E167C7750BB9D19D1B8F420B5B; Path=/; HttpOnly是不是就是這個sessionId,首先客戶端向服務端發起請求的時候,它會返回一個sessionId給客戶端,通過響應頭返回給客戶端的,那么瀏覽器捕獲到響應頭,獲取到對應的sessionId的時候,保存在本地的,保存在本地之后,當你在這邊getSession的時候,他是不是直接讀取本地的sessionId,存放在請求頭里面,是不是這樣的,是不是可以查到里面的信息了,是不是這樣的,當我第二次重新加載的時候,他是不是沒有返回sessionId,因為本地cookie已經緩存了sessionId了,我可以復用的,這就是session的整個原理過程,比較簡單,那么這邊我要總結一下,你們知道session肯定是存在服務器端的,是存放在客戶端的,只是sessionId是存放在客戶端進行保存的 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.0.RELEASE</version><relativePath /> <!-- lookup parent from repository --></parent><properties><weixin-java-mp.version>2.8.0</weixin-java-mp.version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><maven.compiler.encoding>UTF-8</maven.compiler.encoding><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.build.locales>zh_CN</project.build.locales></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- <exclusions> <exclusion> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </exclusion> </exclusions> --></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><!-- Testing Dependencies --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> --><!--spring session 與redis應用基本環境配置,需要開啟redis后才可以使用,不然啟動Spring boot會報錯 --><!-- <dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency> --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency> --></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><maimClass>com.learn.WxMpApplication</maimClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project> server:port: 8080 spring:redis:database: 0host: 59.110.138.145port: 6666password: 1234jedis:pool:max-active: 8max-wait: -1max-idle: 8min-idle: 0timeout: 10000 redis:hostname: 59.110.138.145port: 6666password: 1234 package com.learn.controller;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession;import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;/*** * @author Leon.Sun**/ @SpringBootApplication @RestController public class TestSessionController {/*** 這表示端口號* 這是讀取配置文件里面的* 為什么這么做的目的* 目的是為了區分服務器不同的節點* * * @return*/@Value("${server.port}")private String serverPort;@RequestMapping("/")public String index() {return serverPort;}// 創建session 會話/*** 這段代碼表示什么意思呢* 表示他會去創建一個SESSION* 就是通過拿到request對象* * 比如現在客戶端發起一個createSession請求* 如果他一旦發起createSession請求的時候* 那么這個時候你們去看一段代碼* 看一段什么代碼呢* * * * @param request* @param nameValue* @return*/@RequestMapping("/createSession")public String createSession(HttpServletRequest request, String nameValue) {/*** 看一下這段代碼* 表示什么意思呢* getSession()他這里面可以傳true或者false* 不知道你們有沒有印象* 你們現在可能不理解true和false什么意思* 不理解沒關系* 待會講集群的時候你們瞬間就理解了* 默認是true* 這段代碼表示什么意思呢* 默認 創建一個session* 創建一個SESSION的時候* 默認值是true* 一旦是為true的情況下的時候* 沒有找到對應的SESSION的時候* 自動創建SESSION* 他如果去自動創建這樣的一個SESSION的時候* 一個SESSION他和什么相似* session分為sessionId和sessionValue* 這個你們知道吧* 這個我相信你們知道* 那么在這里我問大家一個問題* session他和什么比較相似* 我不說map集合* session和我們之前學的什么知識比較相似* 和TOKEN* 不是cookie* 他和token非常相似* session本身來說是不是臨時的* 是不是一個臨時的* 他如果是臨時的話* 不是永久有效的* 既然是臨時的話* 和token是不是很相似* 因為我令牌也是做臨時的* sessionId和token令牌也是非常相似的* 保證臨時且唯一* 這個你們一定要記住* 我在后面會講到* 很多公司分布式SESSION用什么解決呢* 就用token解決* 沒有用到Spring-Session* 客戶端向服務器端肯定會發起一個createSession請求* 如果在發起createSession請求的時候* 注意看代碼* 服務器端接收到客戶端請求之后* 會創建一個session* 創建完一個session之后* 通過響應頭返回一個sessionId* 這個是請求的過程* 這個叫做請求過程* 那么反過來再看* 叫做響應的過程* 注意看一下* 請求和響應過程* 第二次請求的時候是這樣的過程* 這個時候什么意思呢* 客戶端向服務器端發起請求的時候* 它會返回一個sessionId* 返回一個sessionId給客戶端* 是不是瀏覽器* 瀏覽器它會怎么做呢* 瀏覽器獲取到sessionId以后* 保存在本地* 既然他的sessionId是保存在本地的話* 那么他和什么技術比較相似* 想想他和什么技術比較相似* 是不是叫做cookie* 是不是非常非常相似* 那么瀏覽器這個時候要怎么做呢* 那么在這邊我要講的是什么呢* 第二次請求* 客戶端讀取到本地的sessionId* 存放在請求頭中* 服務器端從請求頭中獲取到對應的sessionId* 使用sessionId在本地內存中查詢* 你們現在可能還不明白什么意思* 在這里我們打開我們的開發者工具* 當我們發起一個createSession請求的時候* 看一下它是一個什么過程* 我們把日志打開* 一旦向createSession* 首先默認是為true的* 他如果沒有sessionId的話* 創建一個session* 創建一個SESSION之后* 返回一個sessionId* 對應的是存放的值* 我故意把這個session打印出來了* 對應的值是存放在對應的sessionId里面的* 那你們注意看一個效果* 我在這個地方去查詢的時候* 我們再次發起請求* 找到netWork* 找到響應頭* 響應頭是不是把sessionId返回給客戶端* 也就是一個SESSIONID* 客戶端拿到sessionId保存在本地了* * */HttpSession session = request.getSession();System.out.println("存入Session sessionid:信息" + session.getId() + ",nameValue:" + nameValue + ",serverPort:" + serverPort);/*** 在這里存放一個nameValue這個值* */session.setAttribute("name", nameValue);return "success-" + serverPort;}// 獲取session 會話/*** 這里有一個獲取SESSION* * * @param request* @return*/@RequestMapping("/getSession")public Object getSession(HttpServletRequest request) {// 設置為true 情況下的時候,客戶端使用對應的sessionid 查詢不到對應的sesison 會直接創建一個新的session// 設置為false 情況下的時候,客戶端使用對應的sessionid 查詢不到對應的sesison 不 會直接創建一個新的session/*** 這里表示獲取SESSION* * */HttpSession session = request.getSession(false);if (session == null) {return serverPort + " 該服務器上沒有存放對應的session值";}System.out.println("獲取Session sessionid:信息" + session.getId() + "serverPort:" + serverPort);/*** 這里直接獲取getName* * */Object value = session.getAttribute("name");return serverPort + "-" + value;}} package com.learn;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;/*** * @author Leon.Sun**/ @SpringBootApplication public class AppSession {public static void main(String[] args) {/*** 我們直接啟動這個項目* */SpringApplication.run(AppSession.class, args);}}?
總結
以上是生活随笔為你收集整理的Session的底层实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式Session一致性概述
- 下一篇: 服务器集群后产生那些问题