您的位置:首页 > 数据库 > Redis

基于redis的统一session功能实现

2014-11-11 20:40 615 查看
具体实现步骤如下:

1、构建一个filter,CacheSessionFilter,这个filter具体实现的功能是拦截所有使用到session的请求,对请求进行session的封装处理,使得分布式部署下可以同一个用户在不同的服务器中共享同一个session.

2、filter在请求前后的处理逻辑:(1)处理请求逻辑前,加工封装ServletRequest,使得ServletRequest中的getSession在同一个用户下不同机器中获取到的Session是同一个。

(2)处理请求逻辑后,对redis中保存的session进行更新,保存这次请求处理完成时间,用来做下次请求的session过时判断。

3、处理请求逻辑前的具体逻辑:

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
   HttpServletRequest request = (HttpServletRequest)servletRequest;

   if (!shouldFilter(request)) {
     filterChain.doFilter(servletRequest, servletResponse);
     return;
   }
   //*************把访问的客户ip记录在线程里面,目的是为了能在日志里面串起程序执行顺序,与session无关,只是借用这个过滤器程序。
   String clientAddr = InetTool.getClientAddr(request);
   ThreadId.setThreadIdWithIP(clientAddr);
   //*************
   HttpServletResponse response = (HttpServletResponse)servletResponse;
   RequestEventSubject eventSubject = new RequestEventSubject();
   sessionManager=(SessionManager)(PaasContextHolder.getContext().getBean("sessionManager"));
   SessionHttpServletRequestWrapper requestWrapper = new SessionHttpServletRequestWrapper(request, response, this.sessionManager, eventSubject);
   try {
     filterChain.doFilter(requestWrapper, servletResponse);
   }
   finally {
     eventSubject.completed(request, response);
   }
 }

4、SessionHttpServletRequestWrapper继承HttpServletRequestWrapper,重写getSession()方法,若存在session且不过时则用以前的,若过时或者为空则创建:

 public HttpSession getSession(boolean create)
 {
   if ((this.httpSession != null) && (!this.httpSession.expired)) return this.httpSession;
   this.httpSession = this.sessionManager.createSession(this, this.response, this.requestEventSubject, create);
   return this.httpSession;
 }

5、sessionManager中创建session的具体逻辑:

public CacheHttpSession createSession(
SessionHttpServletRequestWrapper request,
HttpServletResponse response,
RequestEventSubject requestEventSubject, boolean create) {
String sessionId = getRequestedSessionId(request);

CacheHttpSession session = null;
if ((StringUtils.isEmpty(sessionId)) && (!create))
return null;
if (StringUtils.isNotEmpty(sessionId)) {
session = loadSession(sessionId);
}
if ((session == null) && (create)) {
session = createEmptySession(request, response);
}
if (session != null)
attachEvent(session, request, response, requestEventSubject);
return session;
}

先从cookies里边取出sessionId,cookies是存在request里边的。

private String getRequestedSessionId(HttpServletRequestWrapper request) {
// String cookid=request.getRequestedSessionId();
// System.out.println(cookid);
Cookie[] cookies = request.getCookies();
if ((cookies == null) || (cookies.length == 0))
return null;
for (Cookie cookie : cookies) {
if (SESSION_ID_COOKIE.equals(cookie.getName()))
return cookie.getValue();
}
return null;
}

如果请求的sessionId为空,且不创建新的session,则返回null,若请求的sessionId为空或者sessionId在storm中找不到对应的session,则新增sessionId,创建新的session,且把session信息保存在cookies中;

private CacheHttpSession createEmptySession(
SessionHttpServletRequestWrapper request,
HttpServletResponse response) {
CacheHttpSession session = new CacheHttpSession();
session.id = createSessionId();
session.creationTime = System.currentTimeMillis();
session.maxInactiveInterval = this.maxInactiveInterval;
session.isNew = true;
if (this.log.isDebugEnabled())
this.log.debug("CacheHttpSession Create [ID=" + session.id + "]");
saveCookie(session, request, response);
return session;
}

如果请求的sessionId不为空,且在redis中存在对应的session,则取redis中的session。

最后若已经去到对应的session,则添加对应的session事件监听:

private void attachEvent(final CacheHttpSession session,
final HttpServletRequestWrapper request,
final HttpServletResponse response,
RequestEventSubject requestEventSubject) {
session.setListener(new SessionListenerAdaptor() {
public void onInvalidated(CacheHttpSession session) {
SessionManager.this.saveCookie(session, request, response);
}
});
requestEventSubject.attach(new RequestEventObserver() {
public void completed(HttpServletRequest servletRequest,
HttpServletResponse response) {
int updateInterval = (int) ((System.currentTimeMillis() - session.lastAccessedTime) / 1000L);
if (SessionManager.this.log.isDebugEnabled()) {
SessionManager.this.log
.debug("CacheHttpSession Request completed [ID="
+ session.id + ",lastAccessedTime="
+ session.lastAccessedTime
+ ",updateInterval=" + updateInterval + "]");
}
if ((!session.isNew)
&& (!session.isDirty)
&& (updateInterval < SessionManager.this.expirationUpdateInterval))
return;
if ((session.isNew) && (session.expired))
return;
session.lastAccessedTime = System.currentTimeMillis();
SessionManager.this.saveSession(session);
}
});
}

监听事件有两块:1、session重新建立时,重新保存session信息到cookies,2、当前请求处理结束后,更新session上次请求时间,以维持会话。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: