使用Spring Session管理会话
2018-05-13 本文已影响0人
土豆了解一下
Spring Sessio项目提供了一个基于redis的用户会话信息管理。
Spring Session的快速入门、在Spring Boot 中使用Spring Session
简单的原理分析 :
-
通过
@EnableRedisHttpSession源码.png@EnableRedisHttpSession
注解创建一个名为springSessionRepositoryFilter
的SessionRepositoryFilter
。
-
SessionRepositoryFilter
继承了OncePerRequestFilter
,而OncePerRequestFilter
继承了javax.servlet.Filter
。OncePerRequestFilter
顾名思义,每次请求都会通过该过滤器。查看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();
}
}
- 通过
SessionRepositoryFilter
过滤器之后,原生的HttpServletRequest
和HttpServletResponse
已经变成了SessionRepositoryRequestWrapper
和SessionRepositoryResponseWrapper
。SessionRepositoryRequestWrapper
继承了HttpServletRequestWrapper
是HttpServletRequest
的一个包装类,查看该类的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
的一个实现类。
优缺点:
- 会话信息存放在服务端,相对比较安全
- 用户同时在线量较多时,会占用大量的内存