xiaoxue85 发表于 2018-11-30 11:41:58

tomcat Session

  org.apache.catalina.connector.Request的getSession方法说起
  public HttpSession getSession() {
      Session session = doGetSession(true);//如果没有找到session默认情况下创建新session
      if (session == null) {
            return null;
      }

      return session.getSession();//这里返回一个StandardSessionFacade对象,主要是因为StandardSession不仅实现了HttpSession还实现了Session接口,如果返回StandardSession对象,那就有可能被用户使用session接口中的方法,为了避免这种情况,为了安全,就返回StandardSessionFacade,他只实现了HttpSession接口。
  }
  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);//估计使用了forward方法,导致重复使用了request
      }

      // Return the requested session if it exists and is valid
      Manager manager = context.getManager();//返回session管理器
      if (manager == null) {
            return null;      // Sessions are not supported
      }
      if (requestedSessionId != null) {//不为null说明http请求报文头中带有sessionID
            try {
                session = manager.findSession(requestedSessionId);//在manager管理的sessions(ConcurrentHashMap)中根据sessionid查找session对象
  } 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()) {//没看懂为啥,估计是因为response已经输出,不能再获取request的session了。
            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())//这种情况是cookie在同一个host下多个应用程序都可见
                && 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;
    }
  至于session的持久化是由线程完成的,这个线程不仅会持久化session,还会实现热加载,如下:
  ContainerBase.threadStart
  protected void threadStart() {

      if (thread != null)
            return;
      if (backgroundProcessorDelay
页: [1]
查看完整版本: tomcat Session