spring session源码解析

Posted 聚变归来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring session源码解析相关的知识,希望对你有一定的参考价值。

模块划分

core部分代码

存储实现部分部分:

jdbc实现

具体存储的实现类
例如:org.springframework.session.jdbc.JdbcOperationsSessionRepository

支持jdbc访问的都可以作为存储介质

JdbcOperationsSessionRepository通过sql来访问后端存储:

  private static final String CREATE_SESSION_QUERY = "INSERT INTO %TABLE_NAME%(PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) VALUES (?, ?, ?, ?, ?, ?, ?)";
  private static final String CREATE_SESSION_ATTRIBUTE_QUERY = "INSERT INTO %TABLE_NAME%_ATTRIBUTES(SESSION_PRIMARY_ID, ATTRIBUTE_NAME, ATTRIBUTE_BYTES) SELECT PRIMARY_ID, ?, ? FROM %TABLE_NAME% WHERE SESSION_ID = ?";
  private static final String GET_SESSION_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES FROM %TABLE_NAME% S LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID WHERE S.SESSION_ID = ?";
  private static final String UPDATE_SESSION_QUERY = "UPDATE %TABLE_NAME% SET SESSION_ID = ?, LAST_ACCESS_TIME = ?, MAX_INACTIVE_INTERVAL = ?, EXPIRY_TIME = ?, PRINCIPAL_NAME = ? WHERE PRIMARY_ID = ?";
  private static final String UPDATE_SESSION_ATTRIBUTE_QUERY = "UPDATE %TABLE_NAME%_ATTRIBUTES SET ATTRIBUTE_BYTES = ? WHERE SESSION_PRIMARY_ID = ? AND ATTRIBUTE_NAME = ?";
  private static final String DELETE_SESSION_ATTRIBUTE_QUERY = "DELETE FROM %TABLE_NAME%_ATTRIBUTES WHERE SESSION_PRIMARY_ID = ? AND ATTRIBUTE_NAME = ?";
  private static final String DELETE_SESSION_QUERY = "DELETE FROM %TABLE_NAME% WHERE SESSION_ID = ?";
  private static final String LIST_SESSIONS_BY_PRINCIPAL_NAME_QUERY = "SELECT S.PRIMARY_ID, S.SESSION_ID, S.CREATION_TIME, S.LAST_ACCESS_TIME, S.MAX_INACTIVE_INTERVAL, SA.ATTRIBUTE_NAME, SA.ATTRIBUTE_BYTES FROM %TABLE_NAME% S LEFT OUTER JOIN %TABLE_NAME%_ATTRIBUTES SA ON S.PRIMARY_ID = SA.SESSION_PRIMARY_ID WHERE S.PRINCIPAL_NAME = ?";
  private static final String DELETE_SESSIONS_BY_EXPIRY_TIME_QUERY = "DELETE FROM %TABLE_NAME% WHERE EXPIRY_TIME < ?";

核心流程


org.springframework.session.web.http.OncePerRequestFilter包装request和response对象

  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);
    SessionRepositoryFilter<S>.SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryFilter.SessionRepositoryRequestWrapper(request, response, this.servletContext);
    SessionRepositoryFilter.SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryFilter.SessionRepositoryResponseWrapper(wrappedRequest, response);

    try {
      filterChain.doFilter(wrappedRequest, wrappedResponse);
    } finally {
      wrappedRequest.commitSession();
    }

  }

org.springframework.session.web.http.SessionRepositoryFilter核心流程:

  • 获取session如果没有判断,是不是因为session无效,无效需要覆盖掉
    -获取session如果有,则如果与当前sessionId不同,则需要回写
  private void commitSession() {
      SessionRepositoryFilter<S>.SessionRepositoryRequestWrapper.HttpSessionWrapper wrappedSession = this.getCurrentSession();
      if (wrappedSession == null) {
        if (this.isInvalidateClientSession()) {
          SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this, this.response);
        }
      } else {
        S session = wrappedSession.getSession();
        this.clearRequestedSessionCache();
        SessionRepositoryFilter.this.sessionRepository.save(session);
        String sessionId = session.getId();
        if (!this.isRequestedSessionIdValid() || !sessionId.equals(this.getRequestedSessionId())) {
          SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
        }
      }

    }

配置类:org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration

配置类:org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessionConfiguration

继承SpringHttpSessionConfiguration

总结:

通过此次源码阅读,更加理解了接口是面对不同场景或变化时,一种智慧的抽象.

参考

https://docs.spring.io/spring-session/docs/current/reference/html5/

以上是关于spring session源码解析的主要内容,如果未能解决你的问题,请参考以下文章

SpringSession的源码解析(生成session,保存session,写入cookie全流程分析)

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

Spring Security---用户名密码登录流程源码解析

转spring源码解析

shiro session和Spring session一样吗?