这篇文章主要讲解的是在SpringBoot项目中,SpringSession的运行原理,同时可以帮助大家更好的对SpringSession进行自定义使用。
一、SpringSession的使用:
1.导入依赖:
我使用的是maven项目,而项目中我们使用的是redis存储session,所以导入的依赖为:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.1.RELEASE</version>
</dependency>
因为spring-session-data-redis里自动引入了spring-data-redis依赖,所以只需要引入这一个就可以连接到redis。
如果用的其他数据源,引入相对应的依赖即可。
2.开启springsession
@SpringBootApplication
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisSessionApplication{
public static void main(String[] args) {
SpringApplication.run(RedisSessionApplication.class,args);
}
}
其中maxInactiveIntervalInSeconds设置的是session的过期时间,这里设置的是30分钟。
另外有的人可能会担心session的清除问题,经过测试springsession的过期时间策略是框架自己实现的,并没有用到redis本身的存储过期时间,当session过期后springsession会调用redis的删除方法将对应的session删除。
3.配置application.yml文件
其实在这里,如果只是做demo的话是不用配置的,当项目启动的时候他会默认访问本地的6379端口。当然需要配置redis集群或者哨兵模式,或者修改默认配置,则需要详细配置。这里不再阐述,有兴趣的朋友可以参考我写的关于配置redis的文章。
以上准备工作就算完成了,启动项目即可。
二、SpringSession的运行原理
1.配置加载
跟本文相关的主要两个配置类RedisHttpSessionConfiguration和SpringHttpSessionConfiguration
(1)以下是RedisHttpSessionConfiguration类中的一些主要配置:
@Bean
public RedisOperationsSessionRepository sessionRepository(
@Qualifier("sessionRedisTemplate") RedisOperations<Object, Object> sessionRedisTemplate,
ApplicationEventPublisher applicationEventPublisher) {
RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(
sessionRedisTemplate);
sessionRepository.setApplicationEventPublisher(applicationEventPublisher);
sessionRepository
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
if (this.defaultRedisSerializer != null) {
sessionRepository.setDefaultSerializer(this.defaultRedisSerializer);
}
String redisNamespace = getRedisNamespace();
if (StringUtils.hasText(redisNamespace)) {
sessionRepository.setRedisKeyNamespace(redisNamespace);
}
sessionRepository.setRedisFlushMode(this.redisFlushMode);
return sessionRepository;
}
主要就是将操纵redis的redisTemplate放入sessionRepository中,而sessionRepository中统一规定了获取session的方法名。即可通过sessionRepository从redis里获取session。
(2)以下是SpringHttpSessionConfiguration中的一些主要配置:
@Bean
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(
SessionRepository<S> sessionRepository) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(
sessionRepository);
sessionRepositoryFilter.setServletContext(this.servletContext);
if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) {
sessionRepositoryFilter.setHttpSessionStrategy(
(MultiHttpSessionStrategy) this.httpSessionStrategy);
}
else {
sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
}
return sessionRepositoryFilter;
}
这里生成了一个SessionRepositoryFilter过滤器,并将上一个配置类中的sessionRepository放入到这个过滤器中。所以这个过滤器就是替换服务器session的关键。
2.执行过滤器
当有http请求发送过来后,将会执行上文中的过滤器。
主要执行的方法:
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(
request, response, this.servletContext);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(
wrappedRequest, response);
HttpServletRequest strategyRequest = this.httpSessionStrategy
.wrapRequest(wrappedRequest, wrappedResponse);
HttpServletResponse strategyResponse = this.httpSessionStrategy
.wrapResponse(wrappedRequest, wrappedResponse);
try {
filterChain.doFilter(strategyRequest, strategyResponse);
}
finally {
wrappedRequest.commitSession();
}
}
这个doFilterInternal方法重写的是OncePerRequestFilter抽象类的方法,而OncePerRequestFilter实现的是Filter接口,在doFilter方法中会调用doFilterInternal。
这里先是将sessionRepository放入到了request的attribute中,然后又用框架中的类SessionRepositoryRequestWrapper对request进行了封装。这个类里有利用sessionRepository创建,获取,删除session的方法。
同时对response也进行了封装,之后再讲封装过得request和response传给下一个过滤器。
至此session的替换就完成了。
3.其他的设置
在配置类里有很多其他的方法,可以让使用者自定义一些策略,比如cookie的序列化策略,session生成的策略等等。只需要手动写一个配置类,创建对应的bean即可,下面是其中一部分可自定的部分。
@Autowired(required = false)
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Autowired(required = false)
public void setCookieSerializer(CookieSerializer cookieSerializer) {
this.cookieSerializer = cookieSerializer;
}
@Autowired(required = false)
public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {
this.httpSessionStrategy = httpSessionStrategy;
}
@Autowired(required = false)
public void setHttpSessionListeners(List<HttpSessionListener> listeners) {
this.httpSessionListeners = listeners;
}
}
以上就是关于springsession原理的介绍,欢迎各位大佬指点