Spring Sessio項目提供了一個基于redis的用戶會話信息管理涮雷。
Spring Session的快速入門馁害、在Spring Boot 中使用Spring Session
簡單的原理分析 :
-
通過
@EnableRedisHttpSession
注解創(chuàng)建一個名為springSessionRepositoryFilter
的SessionRepositoryFilter
痕届。
@EnableRedisHttpSession源碼.png SessionRepositoryFilter
繼承了OncePerRequestFilter
,而OncePerRequestFilter
繼承了javax.servlet.Filter
凳忙。OncePerRequestFilter
顧名思義宫补,每次請求都會通過該過濾器。查看org.springframework.session.web.http.OncePerRequestFilter#doFilter
方法可知碎节,該方法最后會執(zhí)行org.springframework.session.web.http.OncePerRequestFilter#doFilterInternal
抽象方法捧搞,而在SessionRepositoryFilter
中實現(xiàn)了改抽象方法,代碼如下:
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
已經(jīng)變成了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;
}
總結(jié):
通過Filter攔截每一次Http請求,將HttpServletRequest對象做一層包裝晚树,業(yè)務(wù)代碼調(diào)用getSession方法時姻采,實際上是調(diào)用了包裝類中的方法SessionRepositoryFilter.this.sessionRepository .getSession(sessionId)
,而RedisOperationsSessionRepository
正是SessionRepository
的一個實現(xiàn)類爵憎。
優(yōu)缺點:
- 會話信息存放在服務(wù)端慨亲,相對比較安全
- 用戶同時在線量較多時,會占用大量的內(nèi)存