素材巴巴 > 程序开发 >

SpringSession如何管理Session

程序开发 2023-09-09 16:20:05

SpringSession有一套独立的session模型,它和Servlet非常相似,最大的区别是session存放的位置,从StandardManger换到了SessionRepository。通过扩展SessionRepository,可以实现自定义session存储方式。下图是SpringSession和Servlet的session结构的对比:

SpringSession通过注册成Servlet Filter来拦截请求,将请求里注入自己的Session对象,实现session的管理。下面分析一下SpringSession是如何注册Filter和实现SessionRepository扩展的。

注册Filter

SpringSession要注册的Filter类型是SessionRepositoryFilter,它通过ServletContextInitializer 机制在web服务启动时注册Filter。SpringBoot为SpringSession自动装配了ServletContextInitializer。

@Configuration(proxyBeanMethods = false)
 @ConditionalOnBean(SessionRepositoryFilter.class)
 @EnableConfigurationProperties(SessionProperties.class)
 class SessionRepositoryFilterConfiguration {@BeanFilterRegistrationBean> sessionRepositoryFilterRegistration(SessionProperties sessionProperties, SessionRepositoryFilter filter) {FilterRegistrationBean> registration = new FilterRegistrationBean<>(filter);registration.setDispatcherTypes(getDispatcherTypes(sessionProperties));registration.setOrder(sessionProperties.getServlet().getFilterOrder());return registration;}
 }

SessionRepositoryFilter对象是在SpringHttpSessionConfiguration 中注册成Bean,可以通过注解@EnableSpringHttpSession 来开启配置。

@Bean
 public  SessionRepositoryFilter springSessionRepositoryFilter(SessionRepository sessionRepository) {SessionRepositoryFilter sessionRepositoryFilter = new SessionRepositoryFilter<>(sessionRepository);sessionRepositoryFilter.setHttpSessionIdResolver(this.httpSessionIdResolver);return sessionRepositoryFilter;
 }

在初始化SessionRepositoryFilter的时候,依赖SessionRepository 对象,需要我们传进来。这也是

SessionRepository扩展的实现,通过传入不同SessionRepository,实现session存到不同的介质。

@Bean
 public SessionRepository sessionRepository() {return new MapSessionRepository(new ConcurrentHashMap());
 }

至此,SessionRepositoryFilter就注册到FilterChain上了。在请求进来的时候,SessionRepositoryFilter将request和response包装成SessionRepositoryRequestWrapper 和SessionRepositoryResponseWrapper 类型的对象。后面的Filter从request操作session时,都会被SessionRepositoryRequestWrapper拦截,包括创建session。

创建session

SessionRepositoryRequestWrapper 覆盖了HttpSessionWrapper getSession(boolean create) ,在需要的时候会通过SessionRepository 来创建session对象。

@Override
 public HttpSessionWrapper getSession(boolean create) {...S session = SessionRepositoryFilter.this.sessionRepository.createSession();session.setLastAccessedTime(Instant.now());currentSession = new HttpSessionWrapper(session, getServletContext());setCurrentSession(currentSession);return currentSession;
 }

提交session时,也会把数据写回SessionRepository。

private void commitSession() {...	SessionRepositoryFilter.this.sessionRepository.save(session);...
 }

Session持久化到Redis

要把Session存到Redis,只要扩展SessionRepository,把session数据写入Redis。SpringSession为接入Redis提供了默认实现,核心只需两步配置:

  1. 引入spring-session-data-redis


 org.springframework.sessionspring-session-data-redis
 
 org.springframework.bootspring-boot-starter-data-redis
 
  1. 开启@EnableRedisHttpSession注解。如果使用了spring-boot就不用添加注解,会自动注册上去。

@EnableRedisHttpSession
 @AutoConfiguration
 public class AutoConfiguration {
 }


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。