鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

鹏哥之前也没有Spring Session的基础,完全是从零开始,在搜索了无数教程和一步一步的跟踪代码之后,慢慢摸清了一些门道,分享给大家。知识点很多很杂,思路和流程主要参考一网友怀瑾握瑜的博客(https://www.cnblogs.com/lxyit/category/1303872.html),因为作者的思路还算清晰,鹏哥受益匪浅。

上一篇我们听过SpringBoot中启用Spring Session的注解,了解Spring Session的配置过程,这一篇,我们将通过数据流来探讨SpringSession 包装和替换Session的过程。

1. SessionRepositoryFilter

SessionRepositoryFilter是一个Filter过滤器,符合Servlet的规范定义,用来修改包装请求和响应。这里负责包装切换HttpSession至Spring Session的请求和响应。

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

@Order(SessionRepositoryFilter.DEFAULT_ORDER) Order 属性保证了其靠前的执行顺序,可以让每个HttpRequest进入,都会被该Filter包装成切换Session的请求很响应对象。

2. SessionRepositoryRequestWrapper

在spring session中request的实际类型SessionRepositoryRequestWrapper。调用SessionRepositoryRequestWrapper的getSession方法会触发创建spring session,而非web容器的HttpSession。

SessionRepositoryRequestWrapper用来包装原始的HttpServletRequest实现HttpSession切换至Spring Session。是透明Spring Session透明集成HttpSession的关键。

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

SessionRepositoryRequestWrapper继承Servlet规范中定义的包装器HttpServletRequestWrapper。HttpServletRequestWrapper是Servlet规范api提供的用于扩展HttpServletRequest的扩张点——即装饰器模式,可以通过重写一些api达到功能点的增强和自定义。

HttpServletRequestWrapper中持有一个HttpServletRequest对象,然后实现HttpServletRequest接口的所有方法,所有方法实现中都是调用持有的HttpServletRequest对象的相应的方法。继承HttpServletRequestWrapper 可以对其重写。SessionRepositoryRequestWrapper继承HttpServletRequestWrapper,在构造方法中将原有的HttpServletRequest通过调用super完成对HttpServletRequestWrapper中持有的HttpServletRequest初始化赋值,然后重写和session相关的方法。这样就保证SessionRepositoryRequestWrapper的其他方法调用都是使用原有的HttpServletRequest的数据,只有session相关的是重写的逻辑。

再来看下spring session的持久化。上述SessionRepositoryFilter在包装HttpServletRequest后,执行FilterChain中使用finally保证请求的Session始终session会被提交,此提交操作中将sesionId设置到response的head中并将session持久化至存储器中。

持久化只持久spring session,并不是将spring session包装后的HttpSession持久化,因为HttpSession不过是包装器,持久化没有意义。

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

3. SessionRepositoryResponseWrapper

包装响应时为了:确保如果响应被提交session能够被保存。

4. Session接口

spring-session和tomcat中的Session的实现模式上有很大不同,tomcat中直接对HttpSession接口进行实现,而spring-session中则抽象出单独的Session层接口,让后再使用适配器模式将Session适配层Servlet规范中的HttpSession。spring-sesion中关于session的实现和适配整个UML类图如下:

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

Session是spring-session对session的抽象,主要是为了鉴定用户,为Http请求和响应提供上下文过程,该Session可以被HttpSession、WebSocket Session,非WebSession等使用。定义了Session的基本行为:

getId:获取sessionId
setAttribute:设置session属性
getAttribte:获取session属性

ExipringSession:提供Session额外的过期特性。定义了以下关于过期的行为:

setLastAccessedTime:设置最近Session会话过程中最近的访问时间
getLastAccessedTime:获取最近的访问时间
setMaxInactiveIntervalInSeconds:设置Session的最大闲置时间
getMaxInactiveIntervalInSeconds:获取最大闲置时间
isExpired:判断Session是否过期

MapSession:基于java.util.Map的ExpiringSession的实现

RedisSession:基于MapSession和Redis的ExpiringSession实现,提供Session的持久化能力

在RedisSession中有两个非常重要的成员属性:

cached:实际上是一个MapSession实例,用于做本地缓存,每次在getAttribute时无需从Redis中获取,主要为了improve性能
delta:用于跟踪变化数据,做持久化

再来看下RedisSession中最为重要的行为saveDelta——持久化Session至Redis中:

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

5. SessionRepository

创建、保存、获取、删除Session的接口行为。根据Session的不同,分为很多种Session操作仓库。

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

6. HttpSessionStrategy

鹏哥SpringSession三部曲之二 SpringSession 主要类介绍

这里主要介绍CookieHttpSessionStrategy,这个也是默认的策略,可以查看spring-session中类SpringHttpSessionConfiguration,在注册SessionRepositoryFilter Bean时默认采用CookieHttpSessionStrategy:

下面来分析CookieHttpSessionStrategy的原理。该策略使用Cookie来映射Request/Response至Session。即request/requset的head中cookie存储SessionId,当请求至web服务器,可以解析请求head中的cookie,然后获取sessionId,根据sessionId获取spring-session。当创建新的session或者session过期,将相应的sessionId写入response的set-cookie或者从respose中移除sessionId。


分享到:


相關文章: