浅谈Tomcat Session管理分析

2019-10-18 19:52:32刘景俊

Session的生命周期

1.解析获取requestedSessionId

当我们在类中通过request.getSession()时,tomcat是如何处理的,可以查看Request中的doGetSession方法:

protected Session doGetSession(boolean create) {
 
  // There cannot be a session if no context has been assigned yet
  Context context = getContext();
  if (context == null) {
    return (null);
  }
 
  // Return the current session if it exists and is valid
  if ((session != null) && !session.isValid()) {
    session = null;
  }
  if (session != null) {
    return (session);
  }
 
  // Return the requested session if it exists and is valid
  Manager manager = context.getManager();
  if (manager == null) {
    return null;    // Sessions are not supported
  }
  if (requestedSessionId != null) {
    try {
      session = manager.findSession(requestedSessionId);
    } catch (IOException e) {
      session = null;
    }
    if ((session != null) && !session.isValid()) {
      session = null;
    }
    if (session != null) {
      session.access();
      return (session);
    }
  }
 
  // Create a new session if requested and the response is not committed
  if (!create) {
    return (null);
  }
  if ((response != null) &&
      context.getServletContext().getEffectiveSessionTrackingModes().
      contains(SessionTrackingMode.COOKIE) &&
      response.getResponse().isCommitted()) {
    throw new IllegalStateException
    (sm.getString("coyoteRequest.sessionCreateCommitted"));
  }
 
  // Re-use session IDs provided by the client in very limited
  // circumstances.
  String sessionId = getRequestedSessionId();
  if (requestedSessionSSL) {
    // If the session ID has been obtained from the SSL handshake then
    // use it.
  } else if (("/".equals(context.getSessionCookiePath())
      && isRequestedSessionIdFromCookie())) {
    /* This is the common(ish) use case: using the same session ID with
     * multiple web applications on the same host. Typically this is
     * used by Portlet implementations. It only works if sessions are
     * tracked via cookies. The cookie must have a path of "/" else it
     * won't be provided for requests to all web applications.
     *
     * Any session ID provided by the client should be for a session
     * that already exists somewhere on the host. Check if the context
     * is configured for this to be confirmed.
     */
    if (context.getValidateClientProvidedNewSessionId()) {
      boolean found = false;
      for (Container container : getHost().findChildren()) {
        Manager m = ((Context) container).getManager();
        if (m != null) {
          try {
            if (m.findSession(sessionId) != null) {
              found = true;
              break;
            }
          } catch (IOException e) {
            // Ignore. Problems with this manager will be
            // handled elsewhere.
          }
        }
      }
      if (!found) {
        sessionId = null;
      }
    }
  } else {
    sessionId = null;
  }
  session = manager.createSession(sessionId);
 
  // Creating a new session cookie based on that session
  if ((session != null) && (getContext() != null)
      && getContext().getServletContext().
      getEffectiveSessionTrackingModes().contains(
          SessionTrackingMode.COOKIE)) {
    Cookie cookie =
        ApplicationSessionCookieConfig.createSessionCookie(
            context, session.getIdInternal(), isSecure());
 
    response.addSessionCookieInternal(cookie);
  }
 
  if (session == null) {
    return null;
  }
 
  session.access();
  return session;
}