Spring Session解决分布式Session问题的实现原理
使用Spring Session和Redis解决分布式Session跨域共享问题
上一篇介绍了如何使用spring Session和Redis解决分布式Session跨域共享问题,介绍了一个简单的案例,下边就学习一下Spring Session的实现原理。
注:以下步骤是基于XML的方式实现 Spring Session的代码讲解!
先从web.xml文件说起
我们知道Tomcat再启动的时候首先会去加载web.xml
文件,Tomcat启动的时候web.xml
被加载的顺序:context-param -> listener -> filter -> servlet
。
我们在使用Spring Session的时候,我们配置了一个filter,配置代码如下:
介绍一下DelegatingFilterProxy
这个类:
DelegatingFilterProxy
类将通过springSessionRepositoryFilter
这个名称去查找Spring容器中配置的Bean并将其转换为过滤器,对于调用DelegatingFilterProxy
的每个请求,将调用springSessionRepositoryFilter这个过滤器。
如果未指定init-param
参数的话,DelegatingFilterProxy
就会把filter-name
作为要查找的Bean对象,这也是DelegatingFilterProxy
类的作用。可以看出每一个请求都会经过该filter,经过该filter的请求也会相应的经过springSessionRepositoryFilter
这个过滤器,那么我们就接着看一下springSessionRepositoryFilter
这个过滤器。
springSessionRepositoryFilter过滤器的创建
上一过程的DelegatingFilterProxy是从Spring容器中去查找springSessionRepositoryFilter的,那么我们是在哪个地方进行注入springSessionRepositoryFilter的哪?答案是在这里:
我们在Spring的配置文件中手动注入了RedisHttpSessionConfiguration,这是因为我们默认的使用Redis进行存储Session的。
RedisHttpSessionConfiguration 这个类加了Configuration注解,作为配置文件注入。
RedisHttpSessionConfiguration的作用是创建名为springSessionRepositoryFilter 的Spring Bean,继承自Filter。springSessionRepositoryFilter替换容器默认的HttpSession支持为Spring Session,将Session实例存放在Redis中。
(1)RedisHttpSessionConfiguration 继承关系如下:
(2)RedisHttpSessionConfiguration主要方法和属性如下:
(3)RedisHttpSessionConfiguration通过@Bean的方式将RedisMessageListenerContainer、RedisTemplate、RedisOperationsSessionRepository
等注入到Spring容器中。
(4)RedisHttpSessionConfiguration继承了SpringHttpSessionConfiguration这个类,这个类很重要,SpringHttpSessionConfiguration通过@Bean的方式将springSessionRepositoryFilter注入到容器中:
springSessionRepositoryFilter这个过滤器就是前边DelegatingFilterProxy查找的过滤器!
(6)可以看出他是SessionRepositoryFilter类型的,SessionRepositoryFilter的作用就是替换容器默认的javax.servlet.http.HttpSession支持为org.springframework.session.Session。
SessionRepositoryFilter的主要方法和属性如下:
(7)其中SessionRepositoryResponseWrapper、SessionRepositoryRequestWrapper、HttpSessionWrapper为内部类,这个也是很关键的。例如SessionRepositoryRequestWrapper类:
可以看出SessionRepositoryRequestWrapper继承了javax.servlet.http.HttpServletRequestWrapper这个类,我们知道HttpServletRequest接口的默认实现是有HttpServletRequestWrapper的,如下:
(8)因为SessionRepositoryRequestWrapper继承了HttpServletRequestWrapper,而HttpServletRequestWrapper实现了HttpServletRequest接口,在SessionRepositoryRequestWrapper又重写了HttpServletRequest接口中的一些方法,所以才会有:getSession、changeSessionId等这些方法。
到此,我们应该大致明白了,原有的request请求和response都被重新进行了包装。我们也就明白了原有的HttpSeesion是如何被Spring Session替换掉的。
需要注意的是:
The SessionRepositoryFilter must be placed before any Filter
that access the HttpSession or that might commit the response
to ensure the session is overridden and persisted properly.
案例分析
(1)Controller代码如下:
(2)查看效果:
我们通过快捷键查看request.getSession()
的具体实现,就可以看出已经有了SessionRepositoryRequestWrapper
重写的方法。
上述有两个默认的实现,一个是原始的,一个是Spring Session实现的,具体选用哪一种作为实现,这就是我们上边说的DelegatingFilterProxy
代理的作用了,他会将每一个请求过滤,经过DelegatingFilterProxy的每一个请求也会经过springSessionRepositoryFilter过滤器,springSessionRepositoryFilter过滤器就实现了将原有request到SessionRepositoryRequestWrapper的转换,这就是实现了具体的流程!
(3)request.getSession().setAttribute(name, value)的实现:
追踪代码,可以到达下边内容
this.session.setAttribute(name, value) 中session是Session接口的定义,具体实现有:
可以看到有Redis相关的操作!
至此,我们应该清楚了,Spring Session的工作原理了!虽然下边的过程没有再去介绍,但是已经很清楚的理解了。
总结
上述讲述了整个Spring Session的执行流程,关于其他细节并没有过多的学习,后期学习会不断补充文章!
Spring Session解决分布式Session问题的实现原理的更多相关文章
- 使用Spring Session和Redis解决分布式Session跨域共享问题
http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题
- 170222、使用Spring Session和Redis解决分布式Session跨域共享问题
使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...
- Spring Session实现分布式session的简单示例
前面有用 tomcat-redis-session-manager来实现分布式session管理,但是它有一定的局限性,主要是跟tomcat绑定太紧了,这里改成用Spring Session来管理分布 ...
- spring boot 2.x 系列 —— spring boot 实现分布式 session
文章目录 一.项目结构 二.分布式session的配置 2.1 引入依赖 2.2 Redis配置 2.3 启动类上添加@EnableRedisHttpSession 注解开启 spring-sessi ...
- 使用SpringSession和Redis解决分布式Session共享问题
SpringSession优势 遵循servlet规范,同样方式获取session,对应用代码无侵入且对于developers透明化 关键点在于做到透明和兼容 接口适配:仍然使用HttpServlet ...
- 实现session(session数据)的共享,解决分布式session共享
为什么要实现共享? 首先我们应该明白,为什么要实现共享,如果你的网站是存放在一个机器上,那么是不存在这个问题的,因为会话数据就在这台机器,但是如果你使用了负载均衡把请求分发到不同的机器呢?这个时候会话 ...
- ASP.NET性能优化之分布式Session
如果我们正在使用Session,那么构建高性能可扩展的ASP.NET网站,就必须解决分布式Session的架构,因为单服务器的SESSION处理能力会很快出现性能瓶颈,这类问题也被称之为Session ...
- springboot集成redis(mybatis、分布式session)
安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...
- 基于Spring Boot/Spring Session/Redis的分布式Session共享解决方案
分布式Web网站一般都会碰到集群session共享问题,之前也做过一些Spring3的项目,当时解决这个问题做过两种方案,一是利用nginx,session交给nginx控制,但是这个需要额外工作较多 ...
随机推荐
- Replication--分区+复制
1>配置订阅表使用分区,在发布的项目属性中设置"复制分区方案"和"复制索引分区方案"为true,然后初始化订阅 2>在发布数据库上修改发布属性 -- ...
- 造个轮子之基于 Netty 实现自己的 RPC 框架
原文地址: haifeiWu和他朋友们的博客 博客地址:www.hchstudio.cn 欢迎转载,转载请注明作者及出处,谢谢! 服务端开发都会或多或少的涉及到 RPC 的使用,当然如果止步于会用,对 ...
- 南昌网络赛 I. Max answer 单调栈
Max answer 题目链接 https://nanti.jisuanke.com/t/38228 Describe Alice has a magic array. She suggests th ...
- 打扮IDEA更换主题
原文链接:https://blog.csdn.net/github_39577257/article/details/80629750 当我们安装一个新的IDEA工具时,第一次进入时会提示我们选择一个 ...
- POJ-2251-Dungeon Master(3D迷宫,BFS)
Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 48111 Accepted: 18149 ...
- hasattr(object, name)
查看object有没name属性 有返回True 没有返回 False
- 箭头函数中的this和普通函数中的this对比
ES6中新增了箭头函数这种语法,箭头函数以其简洁性和方便获取this的特性.下面来总结一下他们之间的区别: 普通函数下的this: 在普通函数中的this总是代表它的直接调用者,在默认情况下,this ...
- Angular material mat-icon 资源参考_Communication
ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...
- 第二章C++实验
2-28 (1)用if else 语句 #include<iostream> using namespace std; int main(){ char alphabet; while ( ...
- odoo 二次开发的一些原理
一:self是什么 目前新版的Odoo中使用到的self,是对 游标cr.用户ID.模型.上下文.记录集.缓存 的封装. 我们可以通过 self.XX 获取到这些封装的东西,比如:self.cr. ...