使用springboot+springsession实现分布式session以及源码解析
2017-02-23 00:00
1301 查看
摘要: 闲来无事^_^
第一步查看@EnableRedisHttpSession
进二步查看RedisHttpSessionConfiguration
第三步发现其集成自SpringHttpSessionConfiguration查看
继续查看SessionRepositoryFilter
SessionRepository的实现类
使用springboot+springsession实现分布式session以及源码解析
接上问springboot使用redis
springsession是什么
实现分布式session管理为什么要使用springsession
spring全家桶,不想自己实现分布式session管理可以使用添加依赖
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> </dependency>
添加配置
@EnableRedisHttpSession public class HttpSessionConfiguration { }
测试
原理分析
SpringHttpSession第一步查看@EnableRedisHttpSession
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({ java.lang.annotation.ElementType.TYPE }) @Documented @Import(RedisHttpSessionConfiguration.class) @Configuration public @interface EnableRedisHttpSession { ... }
进二步查看RedisHttpSessionConfiguration
@Configuration @EnableScheduling public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration implements EmbeddedValueResolverAware, ImportAware { ... }
第三步发现其集成自SpringHttpSessionConfiguration查看
public class SpringHttpSessionConfiguration implements ApplicationContextAware { private CookieHttpSessionStrategy defaultHttpSessionStrategy = new CookieHttpSessionStrategy(); private boolean usesSpringSessionRememberMeServices; private ServletContext servletContext; private CookieSerializer cookieSerializer; private HttpSessionStrategy httpSessionStrategy = this.defaultHttpSessionStrategy; private List<HttpSessionListener> httpSessionListeners = new ArrayList<HttpSessionListener>(); @PostConstruct public void init() { if (this.cookieSerializer != null) { this.defaultHttpSessionStrategy.setCookieSerializer(this.cookieSerializer); } else if (this.usesSpringSessionRememberMeServices) { DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer(); cookieSerializer.setRememberMeRequestAttribute( SpringSessionRememberMeServices.REMEMBER_ME_LOGIN_ATTR); this.defaultHttpSessionStrategy.setCookieSerializer(cookieSerializer); } } @Bean public SessionEventHttpSessionListenerAdapter sessionEventHttpSessionListenerAdapter() { return new SessionEventHttpSessionListenerAdapter(this.httpSessionListeners); } @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; } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (ClassUtils.isPresent( "org.springframework.security.web.authentication.RememberMeServices", null)) { this.usesSpringSessionRememberMeServices = !ObjectUtils .isEmpty(applicationContext .getBeanNamesForType(SpringSessionRememberMeServices.class)); } } @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; } } 发现其session默认的策略是使用 defaultHttpSessionStrategy=new CookieHttpSessionStrategy();cookie来实现 继续看 @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; } 传入参数SessionRepository的实现类RedisOperationsSessionRepository在RedisHttpSessionConfiguration被进行创建所以sessionRepository使用的就是RedisOperationsSessionRepository用来做于存储
继续查看SessionRepositoryFilter
public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerRequestFilter { ... } 继承自OncePerRequestFilter abstract class OncePerRequestFilter implements Filter { public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { 调用doFilterInternal由SessionRepositoryFilter实现 @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(); } } 包装请求,响应对象 根据策略处理包装请求对象 最后wrappedRequest.commitSession(); HttpSessionWrapper wrappedSession = getCurrentSession(); if (wrappedSession == null) { if (isInvalidateClientSession()) { SessionRepositoryFilter.this.httpSessionStrategy .onInvalidateSession(this, this.response); } } else { S session = wrappedSession.getSession(); SessionRepositoryFilter.this.sessionRepository.save(session); if (!isRequestedSessionIdValid() || !session.getId().equals(getRequestedSessionId())) { SessionRepositoryFilter.this.httpSessionStrategy.onNewSession(session, this, this.response); } } 这就是最终处理,就不做详细解释了
几张图
SessionRepository的实现类
参考
springsession相关文章推荐
- Spring定时任务的实现方式--ScheduledExecutorService and ScheduledExecutorFactoryBean的简单源码解析以及使用
- spring boot session redis 分布式session实现,提供完整源码
- [置顶] Spring-Session实现Session共享实现原理以及源码解析
- Spring-Session实现Session共享实现原理以及源码解析
- 使用springboot+redis实现session共享
- 使用springboot+redis实现session共享
- Spring Boot高级教程之使用Redis实现session共享
- 使用springboot+redis实现session共享
- 以用户登录、注册、添加删除修改为例,解析jdbcTemplate使用方式以及spring注解实现CRUD
- Spring Boot系列(七)Spring Boot使用Redis实现session共享
- spring boot 源码解析26-Liquibase使用及LiquibaseEndpoint解析
- 【Spring实战】----源码解析SessionFactory及Session的管理及getCurrentSession的使用
- Spring MVC整理系列(05)————Spring MVC配置解析及整合SpriSpring MVC之@ModelAttribute、@SessionAttributes以及Model的使用介绍
- 使用springboot+redis实现session共享
- SpringBoot+Redis+Nginx实现负载均衡以及Session缓存共享
- 使用springboot+redis实现session共享
- 使用springboot+redis实现session共享
- 使用springboot+redis实现session共享
- SpringBoot-Mybatis框架使用与源码解析
- springboot源码解析:自己实现一个springboot自动配置