spring boot 分布式session实现
spring boot 分布式session实现
主要是通过包装 HttpServletRequest
将 session
相关的方法进行代理。
具体是的实现就是通过 SessionRepositoryFilter
过滤器将 HttpServletRequest
对象进行包装,当调用 session
相关的方法时,代理到 SessionRepository
的实现类。
我们先看看 SessionRepository
。
public interface SessionRepository<S extends Session> {//创建sessionS createSession();//保存sessionvoid save(S session);//通过session Id查找sessionS findById(String id);//通过session Id删除sessionvoid deleteById(String id);}
SessionRepository
是一个接口,主要用来管理 session
。各种分布式 session
处理方案都需要实现这个接口来实现具体的处理。
SessionRepositoryFilter
是一个过滤器,它的构造方法会接收一个 SessionRepository
的实现类,并且在它的filter方法中会对 HttpServletRequest
、 HttpServletResponse
进行包装,当后续调用到 session
相关的方法时,最终都会调用到 SessionRepository
方法。
SessionRepositoryFilter
继承了 OncePerRequestFilter
OncePerRequestFilter
是一个抽象类,需要子类来实现 doFilterInternal
方法来实现。这个抽象类主要用来控制每个 filter
只执行一次。在它的 doFilter
方法中,又会调用到 doFilterInternal
这个抽象方法。
这个是 SessionRepositoryFilter
的构造方法
public SessionRepositoryFilter(SessionRepository<S> sessionRepository) {if (sessionRepository == null) {throw new IllegalArgumentException("sessionRepository cannot be null");}this.sessionRepository = sessionRepository;}
这个是 SessionRepositoryFilter
的 doFilterInternal
方法,在这个方法中可以看到分别将 request
, response
进行了包装,在这之后获取的 request
, response
实际上是 SessionRepositoryRequestWrapper
、 SessionRepositoryResponseWrapper
类型。
@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,response);try {filterChain.doFilter(wrappedRequest, wrappedResponse);}finally {wrappedRequest.commitSession();}}
之后调用 request.getSesion()
之类 session
相关的方法实际都会调用到 SessionRepositoryRequestWrapper
的方法。
SessionRepositoryRequestWrapper
是 SessionRepositoryFilter
的内部类,所以虽然在 doFilterInternal
方法中创建 SessionRepositoryRequestWrapper
对象时,没有传递 SessionRepository
,但它依旧是可以使用的。
下面简单看下 SessionRepositoryRequestWrapper
的 getSession
方法
@Overridepublic HttpSessionWrapper getSession() {return getSession(true);}@Overridepublic HttpSessionWrapper getSession(boolean create) {......//不相关的代码已经省略,如果对应的session已经存在,就会从上面省略的地方返回对应的session。//如果session不存在,就会在下面去创建session。//可以看到这里是通过SessionRepositoryFilter.this.sessionRepository来创建的S session = SessionRepositoryFilter.this.sessionRepository.createSession();session.setLastAccessedTime(Instant.now());currentSession = new HttpSessionWrapper(session, getServletContext());setCurrentSession(currentSession);return currentSession;}
spring的文档也写了如何使用redis和数据库来实现分布式session。当然spring也已经实现了redis和数据库的具体实现。我们仅仅使用配置就可以来使用。
具体的文档可以查看这里https://docs.spring.io/spring-session/docs/2.2.x/reference/html/httpsession.html#httpsession-redis-jc
比如使用redis来做分布式session
我们只需要进行下面几步
1、配置redis连接的相关信息
2、通过配置启动redis session相关
上面我分别标注了1、2、3。
我们分别来看看。
标注1:先看下
EnableRedisHttpSession
注解
这个类会通过 Import
注解导入 RedisHttpSessionConfiguration
类。而 RedisHttpSessionConfiguration
类又是继承了 SpringHttpSessionConfiguration
。
在 RedisHttpSessionConfiguration
中会实现具体的 session
管理的相关工作。它会创建一个类型为 RedisIndexedSessionRepository
的bean。这个bean就实现了我们开头提到的 SessionRepository
接口,用来执行具体的 session
管理的相关工作。比如将 session
保存到 redis
,从 redis
查找、删除对应 session
等等具体的工作。
在 SpringHttpSessionConfiguration
中会通过注入上面创建的 RedisIndexedSessionRepository
的 bean
,创建 SessionRepositoryFilter
过滤器。
各种分布式实现方案一般都是通过这种方式来实现的。实现具体的 session
管理工作。通过 SpringHttpSessionConfiguration
来完成其他工作。
使用数据库做分布式session的时候也是继承 SpringHttpSessionConfiguration
。
标注2:这个是通过我们在yml中的配置来得到redis的连接工厂
标注3:这个主要是用来指定redis序列化的实现。
上面的是 RedisHttpSessionConfiguration
的方法,在创建 RedisTemplate
、 RedisIndexedSessionRepository
时,都会判断 defaultRedisSerializer
是否为null,不是null的情况下,会设置到 RedisTemplate
、 RedisIndexedSessionRepository
上去。默认的序列化实现,在我们在redis直接查看的时候,就会显示乱码。如下图:
注意:这里我们可以看到 RedisTemplate
并不是通过注入的方式来实现的。所以我们在外面创建 RedisTemplate
的bean对象,在这里时用不到的。
所以就需要我们通过指定序列化实现,注入到 defaultRedisSerializer
属性上。在 RedisHttpSessionConfiguration
这个类中正好有注入的方法:
所以我们就可以在我们的代码中生成 RedisSerializer
类型的 bean
,同时指定 bean
的名字为 springSessionDefaultRedisSerializer
,就可以注入上去。
现在我们在redis查看session时,就不是乱码了。
其他如使用数据库或其他方案来实现分布式session,基本都和redis是类似的。
不过由于各种数据库的语法、等等各方面会稍有差异,所以每个数据库的session的建表语句都是不同的。如文档上所说,需要指定数据库类型和建表脚本。
spring boot 分布式session实现相关推荐
- (38)Spring Boot分布式Session状态保存Redis【从零开始学Spring Boot】
[本文章是否对你有用以及是否有好的建议,请留言] 在使用spring boot做负载均衡的时候,多个app之间的session要保持一致,这样负载到不同的app时候,在一个app登录之后,而访问到另外 ...
- Spring Boot 分布式事物管理
Spring Boot 分布式事物管理 前言 事务是为了保证数据的一致性而产生的.那么分布式事务,顾名思义,就是我们要保证分布在不同数据库.不同服务器.不同应用之间的数据一致性. 在单体项目下数据是存 ...
- Spring Boot——分布式
Spring Boot--分布式 一.分布式 1.分布式的基本概念 2.应用架构的发展 二.Dubbo--Zookeeper 1.ZooKeeper(注册中心) 2.Dubbo 3.测试 三.Spri ...
- Spring Boot 分布式会话
应用范围 为了使Web能适应大规模的访问,需要实现应用程序的集群部署实现集群部署首先要解决session的统一,即需要实现session的共享机制,即分布式会话 分布式Session的实现方式 基于r ...
- spring boot之session store type is 'null'
在网上搜索之后,发现session store type使用来存放session的存储方式,目前Spring boot中只支持Redis方式. 由于本应用暂无需将session放入redis的需求,故 ...
- spring boot 分布式锁组件 spring-boot-klock-starter
基于redis的分布式锁spring-boot starter组件,使得项目拥有分布式锁能力变得异常简单,支持spring boot,和spirng mvc等spring相关项目 快速开始 sprin ...
- spring boot设置session超时时长(自定义spring boot session超时时长)
针对spring boot 2.0 以下版本(亲测1.5.10)设置session超时的方法如下: 1.添加依赖,代码如下: <dependency><groupId>org. ...
- spring boot 分布式事务解决方案
对比LCN和saga(华为apache孵化器项目) ,LCN使用代理连接池封装补偿方法,saga需要手工写补偿方法,相对来说LCN使用更加方便. 参考官方地址: https://github.com/ ...
- spring boot分布式文件系统 毕业设计-附源码182251
摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势:对于分布式文件系统当然也不能排除在外,随着网络技术的不断成熟,带动了分布式文件系统,它彻底改变了过去传 ...
最新文章
- GNU make manual 翻译(六十九)
- at指令 fpga_FPGA毕设系列 | 无线通信
- 【CyberSecurityLearning 24】kali中间人攻击
- 【渝粤教育】国家开放大学2018年春季 0689-22T老年心理健康 参考试题
- 微型计算机接口与技术期末,微机原理与接口技术期末考试试题及答案.pdf
- 日语学习-多邻国-关卡1-家居
- 一文带你读懂Self-Supervised Learning(自监督学习)
- 2018CES智能硬件与新技术盘点
- python 正则表达式语法
- Atitit webshell选型 1. PHP Shell 2.4	1 1.1. 设置密码	4 2. 测试切换目录	4 2.1. 自己实现	5 1.PHP Shell 2.4 Please co
- ecshop 邮件模板 html,给ecshop后台增加新的邮件模板
- Ubuntu LogViewer调试工具
- sklearn 1.0.1官方文档教程
- 2014年FME校园培训考核通过名单
- 西安邮电大学计算机学校转专业,2021年西安邮电大学大一新生转专业及入学考试相关规定...
- 泛微OA e-cology WorkflowCenterTreeData前台接口SQL注入漏洞复现
- 人人都该了解的思维修炼
- 苹果:我们要建设美国新农村
- 【踩坑专栏】win10主页被劫持
- 初级软件测试工程师的面试
热门文章
- python ndarray find_在列表中查找numpy数组的索引(Find index of numpy array in list)
- 微信小程序界面设计入门课程-样式wxss中使用css课程-字体-font-size字体大小
- Qt使用Oracle数据库踩坑教程
- php iconv #039;cp936#039; 转gbk,php cp936转utf8编码转换乱码问题的解决方案
- 看牙医要懂的英语词汇
- 亦菲写的唯一一篇日志
- 为什么要遵循单一职责原则
- 调用百度AI识图实现通用物体和场景识别并重新命名图片,保存结果
- Git - 删除远程分支文件
- idea 使用 git 切换版本