接上問springboot使用redis
實現分佈式session管理html
spring全家桶,不想本身實現分佈式session管理能夠使用html5
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> </dependency>
@EnableRedisHttpSession public class HttpSessionConfiguration { }
SpringHttpSessionjava
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({ java.lang.annotation.ElementType.TYPE }) @Documented @Import(RedisHttpSessionConfiguration.class) @Configuration public @interface EnableRedisHttpSession { ... }
@Configuration @EnableScheduling public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration implements EmbeddedValueResolverAware, ImportAware { ... }
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用來作於存儲
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的實現類 web
springsessionredis