前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring-Session基于Redis管理Session【面试+工作】

Spring-Session基于Redis管理Session【面试+工作】

作者头像
Java帮帮
发布2018-11-08 16:00:33
1.2K0
发布2018-11-08 16:00:33
举报

spring-session管理session实战

1.maven依赖的jar

2.准备spring-session.xml配置文件

session同样是使用redis来做集中式存储,为了方便测试使用本地的6379端口redis,LettuceConnectionFactory是redis连接工厂类;

RedisHttpSessionConfiguration可以简单理解为spring-session使用redis来存储session的功能类,此类本身使用了@Configuration注解,@Configuration注解相当于把该类作为spring的xml配置文件中的,此类中包含了很多bean对象同样也是注解@Bean;

3.准备servelt类

定义了一个简单的servelt,每次请求都在界面打印sessionId;

4.配置web.xml

首先配置了加载类路径下的spring-session.xml配置文件,然后配置了一个名称为springSessionRepositoryFilter的过滤器;这里定义的class是类DelegatingFilterProxy,此类本身并不是过滤器,是一个代理类,可以通过使用targetBeanName参数来指定具体的过滤器类(如下所示),如果不指定默认就是filter-name指定的名称;

5.测试

浏览器中访问:http://localhost:8080/ssession/SSessionTest,查看结果:

查看redis

6.常见问题

具体异常如下:

指定的filter找不到实现类,原因是没有使用配置,此配置可以让系统能够识别相应的注解,而在类RedisHttpSessionConfiguration中使用了大量的注解,其中就有个使用@Bean注解的方法;

spring-session管理session分析

1.DelegatingFilterProxy代理类

DelegatingFilterProxy里没有实现过滤器的任何逻辑,具体逻辑在其指定的filter-name过滤器中;

初始化过滤器,如果没有配置targetBeanName,则直接使用filter-name,这里指定的是springSessionRepositoryFilter,这个名称是一个固定值此filter在RedisHttpSessionConfiguration中被定义;

2.RedisHttpSessionConfiguration配置类

在RedisHttpSessionConfiguration的父类SpringHttpSessionConfiguration中定义了springSessionRepositoryFilter

此方法返回值是SessionRepositoryFilter,这个其实就是真实的过滤器;方法参数sessionRepository同样使用@Bean注解的方式定义;

此方法的返回值是RedisOperationsSessionRepository,有关于session持久化到redis的相关操作都在此类中;

注:持久化到redis只是spring-session的一种方式,也支持持久化到其他数据库中(jdbc,Mongo,Hazelcast等);

3.SessionRepositoryFilter过滤器

所有的请求都会先经过SessionRepositoryFilter过滤器,doFilter方法如下:

request被包装成了SessionRepositoryRequestWrapper对象,response被包装成了SessionRepositoryResponseWrapper对象,SessionRepositoryRequestWrapper中重写了getSession等方法;finally中执行了commitSession方法,将session进行持久化操作;

4.SessionRepositoryRequestWrapper包装类

重点看一下重写的getSession方法,代码如下:

大致分为三步,首先去本地内存中获取session,如果获取不到去指定的数据库中获取,这里其实就是去redis里面获取,sessionRepository就是上面定义的RedisOperationsSessionRepository对象;如果redis里面也没有则创建一个新的session;

5.RedisOperationsSessionRepository类

关于session的保存,更新,删除,获取操作都在此类中;

5.1保存session

每次在消息处理完之后,会执行finally中的commitSession方法,每个session被保存都会创建三组数据,如下所示:

hash结构记录

key格式:spring:session:sessions:[sessionId],对应的value保存session的所有数据包括:creationTime,maxInactiveInterval,lastAccessedTime,attribute;

set结构记录

key格式:spring:session:expirations:[过期时间],对应的value为expires:[sessionId]列表,有效期默认是30分钟,即1800秒;

string结构记录

key格式:spring:session:sessions:expires:[sessionId],对应的value为空;该数据的TTL表示sessionId过期的剩余时间;

相关代码如下:

getMaxInactiveIntervalInSeconds默认是1800秒,expiresInMillis返回了一个到期的时间戳;roundUpToNextMinute方法在此基础上添加了1分钟,并且清除了秒和毫秒,返回的long值被用来当做key,用来记录一分钟内应当过期的key列表,也就是上面的set结构记录;

后面的代码分别为以上三个key值指定了有效期,spring:session:sessions:expires是30分钟,而另外2个都是35分钟;

理论上只需要为spring:session:sessions:[sessionId]指定有效期就行了,为什么还要再保存两个key,官方的说法是依赖redis自身提供的有效期并不能保证及时删除;

5.2定期删除

除了依赖redis本身的有效期机制,spring-session提供了一个定时器,用来定期检查需要被清理的session;

同样是通过roundDownMinute方法来获取key,获取这一分钟内要被删除的session,此value是set数据结构,里面存放这需要被删除的sessionId;

(注:这里面存放的的是spring:session:sessions:expires:[sessionId],并不是实际存储session数据的spring:session:sessions:[sessionId])

首先删除了spring:session:expirations:[过期时间],然后遍历set执行touch方法,并没有直接执行删除操作,看touch方法的注释大致意义就是尝试访问一下key,如果key已经过去则触发删除操作,利用了redis本身的特性;

5.3键空间通知(keyspace notification)

定期删除机制并没有删除实际存储session数据的spring:session:sessions:[sessionId],这里利用了redis的keyspace notification功能,大致就是通过命令产生一个通知,具体什么命令可以配置(包括:删除,过期等)具体可以查看:http://redisdoc.com/topic/not...;

spring-session的keyspace notification配置在ConfigureNotifyKeyspaceEventsAction类中,RedisOperationsSessionRepository负责接收消息通知,具体代码如下:

接收已spring:session:sessions:expires开头的通知,然后截取出sessionId,然后通过sessionId删除实际存储session的数据;

此处有个疑问就是为什么要引入spring:session:sessions:expires:[sessionId]类型key,spring:session:expirations的value直接保存spring:session:sessions:[sessionId]不就可以了吗,这里使用此key的目的可能是让有效期和实际的数据分开,如果不这样有地方监听到session过期,而此时session已经被移除,导致获取不到session的内容;并且在上面设置有效期的时候,spring:session:sessions:[sessionId]的有效期多了5分钟,应该也是为了这个考虑的;

总结

比起之前介绍的tomcat-redis-session-manager来管理session,spring-session引入了更多的键值,并且还引入了定时器,这无疑增加了复杂性和额外的开销,实际项目具体使用哪种方式还需要权衡一下。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java帮帮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档