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实现相关推荐

  1. (38)Spring Boot分布式Session状态保存Redis【从零开始学Spring Boot】

    [本文章是否对你有用以及是否有好的建议,请留言] 在使用spring boot做负载均衡的时候,多个app之间的session要保持一致,这样负载到不同的app时候,在一个app登录之后,而访问到另外 ...

  2. Spring Boot 分布式事物管理

    Spring Boot 分布式事物管理 前言 事务是为了保证数据的一致性而产生的.那么分布式事务,顾名思义,就是我们要保证分布在不同数据库.不同服务器.不同应用之间的数据一致性. 在单体项目下数据是存 ...

  3. Spring Boot——分布式

    Spring Boot--分布式 一.分布式 1.分布式的基本概念 2.应用架构的发展 二.Dubbo--Zookeeper 1.ZooKeeper(注册中心) 2.Dubbo 3.测试 三.Spri ...

  4. Spring Boot 分布式会话

    应用范围 为了使Web能适应大规模的访问,需要实现应用程序的集群部署实现集群部署首先要解决session的统一,即需要实现session的共享机制,即分布式会话 分布式Session的实现方式 基于r ...

  5. spring boot之session store type is 'null'

    在网上搜索之后,发现session store type使用来存放session的存储方式,目前Spring boot中只支持Redis方式. 由于本应用暂无需将session放入redis的需求,故 ...

  6. spring boot 分布式锁组件 spring-boot-klock-starter

    基于redis的分布式锁spring-boot starter组件,使得项目拥有分布式锁能力变得异常简单,支持spring boot,和spirng mvc等spring相关项目 快速开始 sprin ...

  7. spring boot设置session超时时长(自定义spring boot session超时时长)

    针对spring boot 2.0 以下版本(亲测1.5.10)设置session超时的方法如下: 1.添加依赖,代码如下: <dependency><groupId>org. ...

  8. spring boot 分布式事务解决方案

    对比LCN和saga(华为apache孵化器项目) ,LCN使用代理连接池封装补偿方法,saga需要手工写补偿方法,相对来说LCN使用更加方便. 参考官方地址: https://github.com/ ...

  9. spring boot分布式文件系统 毕业设计-附源码182251

    摘  要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势:对于分布式文件系统当然也不能排除在外,随着网络技术的不断成熟,带动了分布式文件系统,它彻底改变了过去传 ...

最新文章

  1. GNU make manual 翻译(六十九)
  2. at指令 fpga_FPGA毕设系列 | 无线通信
  3. 【CyberSecurityLearning 24】kali中间人攻击
  4. 【渝粤教育】国家开放大学2018年春季 0689-22T老年心理健康 参考试题
  5. 微型计算机接口与技术期末,微机原理与接口技术期末考试试题及答案.pdf
  6. 日语学习-多邻国-关卡1-家居
  7. 一文带你读懂Self-Supervised Learning(自监督学习)
  8. 2018CES智能硬件与新技术盘点
  9. python 正则表达式语法
  10. Atitit webshell选型 1. PHP Shell 2.4 1 1.1. 设置密码 4 2. 测试切换目录 4 2.1. 自己实现 5 1.PHP Shell 2.4 Please co
  11. ecshop 邮件模板 html,给ecshop后台增加新的邮件模板
  12. Ubuntu LogViewer调试工具
  13. sklearn 1.0.1官方文档教程
  14. 2014年FME校园培训考核通过名单
  15. 西安邮电大学计算机学校转专业,2021年西安邮电大学大一新生转专业及入学考试相关规定...
  16. 泛微OA e-cology WorkflowCenterTreeData前台接口SQL注入漏洞复现
  17. 人人都该了解的思维修炼
  18. 苹果:我们要建设美国新农村
  19. 【踩坑专栏】win10主页被劫持
  20. 初级软件测试工程师的面试

热门文章

  1. python ndarray find_在列表中查找numpy数组的索引(Find index of numpy array in list)
  2. 微信小程序界面设计入门课程-样式wxss中使用css课程-字体-font-size字体大小
  3. Qt使用Oracle数据库踩坑教程
  4. php iconv #039;cp936#039; 转gbk,php cp936转utf8编码转换乱码问题的解决方案
  5. 看牙医要懂的英语词汇
  6. 亦菲写的唯一一篇日志
  7. 为什么要遵循单一职责原则
  8. 调用百度AI识图实现通用物体和场景识别并重新命名图片,保存结果
  9. Git - 删除远程分支文件
  10. idea 使用 git 切换版本