[TOC]
目的
学习一下spring-session中包含的一些设计,理解其设计思想,其次是了解内部源码,逻辑。
工程结构
来自spring-session的思考
首先思考一下spring-session要解决什么问题,其次达到什么样的设计要求,
我们首先来正向推导,然后在结合代码逆向推导,他达到了一些什么要求
基本要求
- 原业务无感知(重要)
- 支持多种存储介质
- 支持多种servlet容器(重要)
- 性能
- 稳定性、可靠性
要想做到第1、3条,基本限定必须要基于标准servlet协议
基础知识
HttpSession (javax.servlet.http) 接口
Session (Spring-Session 接口) MapSession RedisSession JdbcSession
ServletRequest->HttpServletRequest (javax.servlet;)
ServletRequestWrapper(类)->HttpServletRequestWrapper(类)(javax.servlet;)
SessionRepository(Spring Session接口) 一个管理Session实例的仓库
SessionRepositoryFilter(将spring-session 里面的Session转换 Httpsession 的实现)
SessionRepositoryRequestWrapper、SessionRepositoryResponseWrapper (spring-session)
2种设计模式
- 适配器模式
- 包装着模式
思考 为什么要用适配器模式?spring为什么要另起一个Session的接口
1、通过调整HttpSessionAdapter 就可以屏蔽两种接口之间的差异
2、不仅仅能支持和满足servlet规范,还能方便扩展其他规范
关键类
spring-session-core | spring-session-data-redis |
---|---|
SessionRepositoryFilter | |
Session | RedisSession RedisOperationsSessionRepositoryn内部类 |
SessionRepository | RedisOperationsSessionRepository |
SpringHttpSessionConfiguration | RedisHttpSessionConfiguration |
各个主要配置类作用
@EnableRedisHttpSession位于spring-session-data-redis module 中
并@Import RedisHttpSessionConfiguration.class
RedisHttpSessionConfiguration继承spring-session-core中的SpringHttpSessionConfiguration
其中SpringHttpSessionConfiguration只关注filter,cookie解析,sessionId解析
RedisHttpSessionConfiguration 主要作用构建SessionRepository (创建redis 序列化, redis连接工厂,命名空间,缓存有效期)
redisMessageListenerContainer 缓存的一些监听器
整体架构
获取session
SessionRepositoryRequestWrapper getSession
1 |
|
session创建
RedisOperationSessionsRepository.java
1 | public RedisSession createSession() { |
session提交
session提交一共干了如下几件事
1 |
|
RedisOperationsSessionRepository.java
1 | private void save() { |
为何要这样设计呢
假设一下
- 解决过期Session不能被及时清除的问题 (定时任务每隔一个钟去访问redis,触发清除)
- 为了不遍历全空间数据,将一分钟过期的数据放到同一个set下面,每分钟的定时任务只去清除这个set下的数据
- 即使数据过期,也不要立即删除当前,还有过期的事件处理
session过期
需要监听session过期事件,并且进行触发
RedisHttpSessionConfiguration.java
1 | //定时任务扫描 |
1 | public void cleanExpiredSessions() { |
RedisOperationsSessionRepository.java
1 | public void onMessage(Message message, byte[] pattern) { |
参考文献
https://github.com/spring-projects/spring-session/issues/92