主要知识:
了解SpringSession的原理和学习源码。
开始学习:
注意:相同的类名都是用了相同的颜色标注,前后寻找时找相同颜色即可。并且建议边看源码边看博客。
首先先找到SpringSession的关键开启注解:@EnableRedisHttpSession,这个注解可以开启使用redis作为Session的存储,当然如果要使用还需配置redis。
点进去,发现它导入了一个RedisHttpSessionConfiguration配置类。
看看它都干了些啥,点进这个类,向下滑,可以发现它向容器中注入了一个RedisIndexedSessionRepository类(旧版叫做RedisOperationsSessionRepository类)
这个类是干什么的?通过ctrl+f12查看其封装方法和结构,发现其中有各种增删改查方法,所以可以初步认定这是操作redis的增删改查的dao类,先把它记一下。
继续向上滑查看这个类,发现其继承了一个SpringHttpSessionConfiguration配置类。
这个类是关键,点进去,向下滑,可以发现其向容器中注入了一个session的过滤器SessionRepositoryFilter类(这是一个session存储的过滤器,是SpringSession的核心之一):
逐个点进其父类查看,可以发现它其实实现了Http的Filter过滤器:
这就说明SpringSession往容器中放了一个过滤器,每个请求进来都会被过滤。
回到过滤器SessionRepositoryFilter类,其只有唯一一个有参构造,其参数是还是SessionRepository类型,表面意思这是一个Session的仓库,那这个仓库是哪来的?和它像的有一个RedisIndexedSessionRepository类,也就是刚刚那个操作redis的dao类,向上寻找它的父类,可以发现,RedisIndexedSessionRepository父类的父类其实就是SessionRepository:
所以操作redis的dao类RedisIndexedSessionRepository通过了自动注入注入到了SessionRepositoryFilter过滤器中。
那这样又有什么用呢?
继续看过滤器SessionRepositoryFilter类,在这个类中向下滑,可以发现一个比较特别的类:doFilterInternal:
这个类似乎和过滤有关,看看有哪些类引用了这个类:
真正在doFilter时其实调用的就是这个类。
来个手撕分析:
1、第一步setAttribute相当于向当前请求中放了处理session的sessionRepository,而这个sessionRepository其实就是操作redis的那个dao类。
2、然后将request, response打包成了一个wrappedRequest,即包装原始请求对象。
3、然后将wrappedRequest和response再打包成一个wrappedResponse,即包装原始响应对象。
4、最后再把包装后的request和response放行给我们的controller,应用到了我们后面的整个执行链。
最后获取到的session对象其实是包装后的request中自定义的getSession方法返回的session对象,这里就把前面看到的都串在一起了,所以这个类其实才是整个SpringSession的核心。
SpringSession工作步骤:首先请求进来先通过其自定义的过滤器,把原始request和原始response拿到,加入SpringSession为我们提供的各种操作redis的方法和其它扩展功能,再将打包后的request和response给我们返回,最后我们需要时拿到的request和response其实就就是已经被覆盖了的request和response了。