概述
本文基于以下组合的应用,通过源代码分析一下一个Spring Boot
应用中Spring Session
的配置过程:
Spring Boot 2.1.3.RELEASE
Spring Session Core 2.1.4.RELEASE
Spring Session Data Redis 2.1.3.RELEASE
Spring Web MVC 5.1.5.RELEASE
在前两篇文章中,我们分析了SessionAutoConfiguration
和RedisSessionConfiguration
。SessionAutoConfiguration
是Spring Boot
关于Spring Session
的自动配置类,它在特定的条件和时机满足时调用RedisSessionConfiguration
,而RedisSessionConfiguration
使用配置属性对基于Redis
的Spring Session
的最终工作组件进行真正的配置最终生成一个SessionRepositoryFilter bean
。而这篇文章,我们来看看SessionRepositoryFilterConfiguration
,它的任务是将SessionRepositoryFilter bean
注册到Servlet
容器。只有SessionRepositoryFilter
注册到了Servlet
容器,用户请求处理过程中会HttpSession
的操作才会最终由Spring Session
机制服务(替换了Servlet
容器原生的HttpSession
机制)。
源代码分析
SessionRepositoryFilterConfiguration
package org.springframework.boot.autoconfigure.session;
// 省略 import 行
@Configuration
// 在 bean SessionRepositoryFilter 存在的的情况下才生效
@ConditionalOnBean(SessionRepositoryFilter.class)
// 确保配置属性项 server.session.* 提取到 bean SessionProperties
@EnableConfigurationProperties(SessionProperties.class)
class SessionRepositoryFilterConfiguration {
// 定义bean FilterRegistrationBean, 这是一个过滤器注册bean,它的任务是将一个过滤器注册到
// Servlet 容器,这里的过滤器指的就是 bean SessionRepositoryFilter
@Bean
public FilterRegistrationBean<SessionRepositoryFilter<?>> sessionRepositoryFilterRegistration(
SessionProperties sessionProperties, SessionRepositoryFilter<?> filter) {
FilterRegistrationBean<SessionRepositoryFilter<?>> registration = new FilterRegistrationBean<>(
filter);
registration.setDispatcherTypes(getDispatcherTypes(sessionProperties));
registration.setOrder(sessionProperties.getServlet().getFilterOrder());
return registration;
}
// 从配置属性项中获取所指定的 DispatcherType 集合,如果配置属性中没有指定该信息,则使用
// 缺省值 : DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST
private EnumSet<DispatcherType> getDispatcherTypes(
SessionProperties sessionProperties) {
SessionProperties.Servlet servletProperties = sessionProperties.getServlet();
if (servletProperties.getFilterDispatcherTypes() == null) {
return null;
}
return servletProperties.getFilterDispatcherTypes().stream()
.map((type) -> DispatcherType.valueOf(type.name())).collect(Collectors
.collectingAndThen(Collectors.toSet(), EnumSet::copyOf));
}
}
总结
SessionRepositoryFilterConfiguration
的配置任务相对简单,在SessionAutoConfiguration
,RedisSessionConfiguration
做了大量的检测和配置工作之后,可以认为SessionRepositoryFilterConfiguration
就做了一件事情,将已经存在的bean SessionRepositoryFilter
包装成一个FilterRegistrationBean bean
,这样Servlet
容器启动时,bean SessionRepositoryFilter
会被注册到Servlet
容器。
SessionRepositoryFilterConfiguration
并不仅仅针对基于Redis
的Spring Session
机制,如果Spring Session
实际使用的存储库是其他类型,比如MongoDB
,Hazelcast
或者基于关系型数据库,也会使用SessionRepositoryFilterConfiguration
。