Spring Session原理及源碼分析

Spring Session在不改變原有使用方式的前提下可以管理session。
從註解@EnableSpringHttpSession入手:

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({ java.lang.annotation.ElementType.TYPE })
@Documented
@Import(SpringHttpSessionConfiguration.class)
@Configuration
public @interface EnableSpringHttpSession {
}

發現導入了配置類
SpringHttpSessionConfiguration

@Configuration
public class SpringHttpSessionConfiguration {

  private CookieHttpSessionStrategy defaultHttpSessionStrategy = new CookieHttpSessionStrategy();

  private HttpSessionStrategy httpSessionStrategy = this.defaultHttpSessionStrategy;

  private List<HttpSessionListener> httpSessionListeners = new ArrayList<HttpSessionListener>();

  private ServletContext servletContext;

  @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;
  }

  @Autowired(required = false)
  public void setServletContext(ServletContext servletContext) {
      this.servletContext = servletContext;
  }

  @Autowired(required = false)
  public void setCookieSerializer(CookieSerializer cookieSerializer) {
      this.defaultHttpSessionStrategy.setCookieSerializer(cookieSerializer);
  }

  @Autowired(required = false)
  public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) {
      this.httpSessionStrategy = httpSessionStrategy;
  }

  @Autowired(required = false)
  public void setHttpSessionListeners(List<HttpSessionListener> listeners) {
      this.httpSessionListeners = listeners;
  }
}

最底下有四個可以配置的Spring Session方式。看名字可以看出他們的作用。
這個配置往Spring容器中配置兩個bean。
SessionEventHttpSessionListenerAdapter session事件的監聽器適配器
SessionRepositoryFilter session 持久化的過濾器,這是Spring Session的核心。

SessionRepositoryFilter 可以支持兩種策略,

  1. CookieHttpSessionStrategy是基於Cookie的默認實現。

  2. MultiHttpSessionStrategy可以支持多個用戶在一個瀏覽器上。

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();
  }
  HttpServletRequest strategyRequest = this.httpSessionStrategy
        .wrapRequest(wrappedRequest, wrappedResponse);
  HttpServletResponse strategyResponse = this.httpSessionStrategy
        .wrapResponse(wrappedRequest, wrappedResponse);
}

SessionRepositoryRequestWrapper及
SessionRepositoryResponseWrapper是將
HttpServletRequest、HttpServletResponse包裝成的可以提供session持久化功能的類。

HttpServletRequest strategyRequest = this.httpSessionStrategy
      .wrapRequest(wrappedRequest, wrappedResponse);
HttpServletResponse strategyResponse = this.httpSessionStrategy
      .wrapResponse(wrappedRequest, wrappedResponse);

利用多態完成request及response的實現轉換。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章