SpringSession
官方文档:
https://spring.io/projects/spring-session
一.Spring Session简介
1. Spring Session概念:
Spring Session 是Spring家族中的一个子项目,Spring Session提供了用于管理用户会话信息的API和实现。
它把servlet容器实现的httpSession替换为spring-session,专注于解决 session管理问题,Session信息存储在Redis中,可简单快速且无缝的集成到我们的应用中
2. Spring Session的特性:
Spring Session使支持集群会话变得很简单,而无需绑定到特定于应用程序容器的解决方案。它还提供与以下内容的透明集成:
-
HttpSession -允许以应用程序容器(即Tomcat)中立的方式替换HttpSession,并支持在标头中提供会话ID以与RESTful API一起使用
-
WebSocket -提供了在接收WebSocket消息时使HttpSession保持活动状态的功能
-
WebSession -允许以应用程序容器中立的方式替换Spring WebFlux的WebSession
3. Session会话共享方案
第一种是使用容器扩展插件来实现,比如基于Tomcat的tomcat-redis-session-manager插件,基于Jetty的jetty-session-redis插件、memcached-session-manager插件;这个方案的好处是对项目来说是透明的,无需改动代码,但是由于过于依赖容器,一旦容器升级或者更换意味着又得重新配置
第二种是 使用Nginx负载均衡的ip_hash策略实现用户每次访问都绑定到同一台具体的后台tomcat服务器实现session总是存在
第三种是自己写一套Session会话管理的工具类,在需要使用会话的时候都从自己的工具类中获取,而工具类后端存储可以放到Redis中,这个方案灵活性很好,但开发需要一些额外的时间
第四种是使用框架的会话管理工具,也就是本文所使用的Spring session,这个方案既不依赖tomcat容器,又不需要改动代码,由Spring session框架为我们提供,可以说是目前非常完美的session共享解决方案
4.spring-session分为以下核心模块:
SessionRepositoryFilter:Servlet规范中Filter的实现,用来切换HttpSession至Spring Session,包装HttpServletRequest和HttpServletResponse
HttpServerletRequest/HttpServletResponse/HttpSessionWrapper包装器:包装原有的HttpServletRequest、HttpServletResponse和Spring Session,实现切换Session和透明继承HttpSession的关键之所在
Session:Spring Session模块
SessionRepository:管理Spring Session的模块
HttpSessionStrategy:映射HttpRequst和HttpResponse到Session的策略
二.Spring Session示例
1.在idea中 新建两个 springboot 项目
springsession01 和 springsession02
2. 导入依赖
<-- 父依赖 --> <parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>2.3.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 引入 springboot&redis 整合场景 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 引入 springboot&springsession 整合场景 --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency> </dependencies> |
3. 分别写两个项目(springsession01 和 springsession02)的主启动类
4.在springsession01 中 写 TestController
设置session
package com.crowd.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController public class TestController { @RequestMapping("/test/spring/session/save") public String testSession(HttpSession session){ session.setAttribute("name","hjj"); return "测试 session 共享"; } } |
5.在springsession02 中 获取session中的
@RestController public class TestController { @RequestMapping("/test/spring/session/retrieve") public String testSession(HttpSession session){ String name = (String) session.getAttribute("name"); return name; } } |
6. 配置 application.yml
springsession01中:
#redis 配置 spring: redis: host: 127.0.0.1 jedis: pool: max-idle: 100 session: store-type: redis # springsession 配置 type= redis |
springsession02中:
#redis 配置 spring:
redis: host: 127.0.0.1 #redis连接池配置 jedis: pool: max-idle: 100 session: store-type: redis # springsession 配置 type= redis # server: port: 8383 |
7. 分别启动两个 项目 测试
http://localhost:8080/test/spring/session/save
http://localhost:8383/test/spring/session/retrieve
Windows+R 输入cmd
在redis 中查找有没有 name
注意:
如果是Redis在linux 上面的 ,首先要开启虚拟机,开启Redis服务
还要修改 application.yml 中的
redis:
host:
如果 启动 报错
Exception in thread “main“ redis.clients.jedis.exceptions.JedisDataException
原因分析:
1)机器之间网络无法联通
2)ip和端口号不正确
3)虚拟机中防火墙的原因(可能性较大)
4)redis.conf 中bind 127.0.0.1 未用#注释掉
参考解决方案:
1,关闭linux防火墙 Centos6 查看防火墙状态: [root@centos6 ~]# service iptables status iptables:未运行防火墙。 开启防火墙: [root@centos6 ~]# service iptables start 关闭防火墙: [root@centos6 ~]# service iptables stop centos7 #查看防火墙状态:,注意firewall与-cmd之间无空格 firewall-cmd --state #关闭防火墙 systemctl stop firewalld.service #开启防火墙 systemctl start firewalld.service #禁用防火墙 systemctl disable firewalld.service 2,注释 redis.conf 配置文件中的 # bind 127.0.0.1,并将protected-mode设为no
vim redis.conf 2. 修改 #bind 127.0.0.1 protected-mode no |