什么是 HttpSession
是 JavaWeb 服務端提供的用來建立與客戶端會話狀態的對象。
什么是 Session 共享
是指在一個瀏覽器對應多個 Web 服務時,服務端的 Session 數據需要共享。
Session 共享應用場景
1) 單點登錄
2) Web 服務器集群等場景都需要用到
Session 復制
通過對應用服務器的配置開啟服務器的 Session 復制功能,在集群中的幾台服務器之間同步 Session 對象,使得每台服務器上都保存所有的 Session 信息,這樣任何一台宕機都不會導致 Session 的數據丟失,服務器使用 Session 時,直接從本地獲取。這種方式的缺點也比較明顯。因為 Session 需要時時同步,並且同步過程是有應用服務器來完成,由此對服務器的性能損耗也比較大。
Session 綁定
利用 hash 算法,比如 nginx 的 ip_hash,使得同一個 Ip 的請求分發到同一台服務器上。這種方式不符合對系統的高可用要求,因為一旦某台服務器宕機,那么該機器上的Session 也就不復存在了,用戶請求切換到其他機器后么有 Session,無法完成業務處理。
利用 Cookie 記錄 Session
Session 記錄在客戶端,每次請求服務器的時候,將 Session 放在請求中發送給服務器,服務器處理完請求后再將修改后的 Session 響應給客戶端。這里的客戶端就是 cookie。
利用 cookie 記錄 Session 的也有缺點,比如受 cookie 大小的限制,能記錄的信息有限,安全性低,每次請求響應都需要傳遞 cookie,影響性能,如果用戶關閉 cookie,訪問就不正常。
Session 服務器
Session 服務器可以解決上面的所有的問題,利用獨立部署的 Session 服務器統一管理
Session,服務器每次讀寫 Session 時,都訪問 Session 服務器。對於 Session 服務器,我們可以使用 Redis 或者 MongoDB 等內存數據庫來保存 Session中的數據,以此替換掉服務中的 HttpSession。達到 Session 共享的效果。
什么是 Spring Session
Spring Session 是 Spring 的項目之一。Spring Session 提供了一套創建和管理 ServletHttpSession 的方案,默認采用外置的 Redis 來存儲 Session 數據,以此來解決 Session 共享的問題。
Spring Session 的使用
安裝 Redis(單機)
第一步 需要在 linux 系統中安裝 gcc
命令:
yum install-y gcc-c++
第二步 需要將下載好的 redis 壓縮包添加到 linux 服務器中
版本:redis-3.0.0.tar.gz
redis 的版本:副版本號奇數版本號是測試版,不建議在生產環境中使用。
偶數版本時穩定版建議在生產環境中使用。3.0 版本更新比較大。集成了集群技術
第三步 解壓壓縮包
命令:
tar-zxvf redis......
第四步 編譯 redis
命令:進入 redis 的解壓完畢的根目錄下 執行命令:
make
第五步 安裝 redis
命 令 : 進 入 redis 的 解 壓 完 畢 的 根 目 錄 下 , 執 行 命 令 :
make installPREFIX=/usr/local/redis
第六步:啟動 redis
1,前端啟動
在 bin 目錄下執行命令:
./redis-server
(ctrl+c)退出 redis
2.后端啟動
(1)先將 redis 解壓目錄下的 redis.conf 文件拷貝到 安裝好的 redis 的 bin 目錄下
命令:
cp redis.conf /usr/local/redis/bin
(2)修改拷貝過來的 redis.conf 配置文件
命令:
vim redis.conf
將 daemonize no 改為 yes
(3)啟動 redis
在 bin 目錄下執行命令:
./redis-server redis.conf
(4)查看 redis 啟動是否成功
輸入命令:
ps aux|grep redis
(5) 關閉 redis 的命令
./redis-cli shutdown
第七步:測試 redis
在 bin 目錄下啟動 redis 自帶的客戶端
./redis-cli
常見 redis 命令:
ping
如果正常的啟動應該會影響pong
搭建案例環境
版本介紹
JDK:1.8
Spring Boot:2.1.6.RELEASE
Spring Session:Bean-SR3
創建項目
創建父工程 spring_session

創建模塊 session_service1

創建模塊 session_service2

修改 POM 文件添加坐標依賴
修改父工程 POM 文件
<?xml version="1.0" encoding="UTF-8"?> <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.bjsxt</groupId> <artifactId>spring_session</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>session_server1</module> <module>session_server2</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.9.RELEASE</version> </parent> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-bom</artifactId> <version>Bean-SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!--web Starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Redis Starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.4.7.RELEASE</version> </dependency> <!--Spring session data redis--> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> <!--Lettuce 是一個基於Netty的NIO方式處理Redis的技術--> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </dependency> </dependencies> </project>
添加配置文件
session_service1
server: port: 8081 spring: application: name: server1 redis: host: 192.168.181.136 port: 6379 database: 0
session_service2
server: port: 8082 spring: application: name: server2 redis: host: 192.168.181.136 port: 6379 database: 0
創建啟動類
com.bjsxt.SessionServer1Application
package com.bjsxt; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; @SpringBootApplication @EnableRedisHttpSession(redisNamespace = "user")/*(maxInactiveIntervalInSeconds = 10)配置Redis的失效時間*/ public class SessionServer1Application { public static void main(String[] args) { SpringApplication.run(SessionServer1Application.class,args); } }
com.bjsxt.SessionServer2Application
package com.bjsxt; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; @SpringBootApplication @EnableRedisHttpSession(redisNamespace = "user")/*(maxInactiveIntervalInSeconds = 10)配置Redis的失效時間*/ public class SessionServer2Application { public static void main(String[] args) { SpringApplication.run(SessionServer2Application.class,args); } }
編寫測試代碼測試效果
session_service1
創建 Controller
package com.bjsxt.controller; import com.bjsxt.pojo.Roles; import com.bjsxt.pojo.User; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController @RequestMapping("/server1") public class WebController { @RequestMapping("/setMsg") public String setMsg(HttpSession session,String msg){ session.setAttribute("msg",msg); return "ok"; } @RequestMapping("/setUser") public String setUser(HttpSession session){ Roles roles=new Roles(); roles.setRid(1001); roles.setName("VIP會員"); User user=new User(); user.setName("yxf"); user.setAge(22); user.setRoles(roles); session.setAttribute("user",user); return "success"; } }
session_service2
com.bjsxt.controller.WebController
package com.bjsxt.controller; import com.bjsxt.pojo.User; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController @RequestMapping("/server2") public class WebController { @RequestMapping("/getMsg") public String getMsg(HttpSession session){ String msg = (String) session.getAttribute("msg"); return msg; } @RequestMapping("/getUser") public User getUser(HttpSession session){ User user = (User) session.getAttribute("user"); return user; } }