使用Spring Session管理会话

Spring Sessio项目提供了一个基于redis的用户会话信息管理。
Spring Session的快速入门、在Spring Boot 中使用Spring Session

简单的原理分析

  1. 通过@EnableRedisHttpSession注解创建一个名为springSessionRepositoryFilterSessionRepositoryFilter

    @EnableRedisHttpSession源码.png

  2. SessionRepositoryFilter继承了OncePerRequestFilter,而OncePerRequestFilter继承了javax.servlet.FilterOncePerRequestFilter顾名思义,每次请求都会通过该过滤器。查看org.springframework.session.web.http.OncePerRequestFilter#doFilter方法可知,该方法最后会执行org.springframework.session.web.http.OncePerRequestFilter#doFilterInternal抽象方法,而在SessionRepositoryFilter中实现了改抽象方法,代码如下:

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();
    }
}
  1. 通过SessionRepositoryFilter过滤器之后,原生的HttpServletRequestHttpServletResponse已经变成了SessionRepositoryRequestWrapperSessionRepositoryResponseWrapperSessionRepositoryRequestWrapper继承了HttpServletRequestWrapperHttpServletRequest的一个包装类,查看该类的getSession方法:
private S getSession(String sessionId) {
    S session = SessionRepositoryFilter.this.sessionRepository
            .getSession(sessionId);
    if (session == null) {
        return null;
    }
    session.setLastAccessedTime(System.currentTimeMillis());
    return session;
}   

总结
通过Filter拦截每一次Http请求,将HttpServletRequest对象做一层包装,业务代码调用getSession方法时,实际上是调用了包装类中的方法SessionRepositoryFilter.this.sessionRepository .getSession(sessionId),而RedisOperationsSessionRepository正是SessionRepository的一个实现类。

优缺点

  • 会话信息存放在服务端,相对比较安全
  • 用户同时在线量较多时,会占用大量的内存

你可能感兴趣的:(使用Spring Session管理会话)