SoFunction
Updated on 2025-04-05

Implementation method of tomcat sharing multiple web application sessions

Implementation method of tomcat sharing multiple web application sessions

question

A friend asked a question today, roughly: two Java webs under tomcat, one is the mall and the other is the live broadcast. After logging in from the mall, jump to the live broadcast, and found that they are in a non-login state.

Solution

  1. Extract the session into a session service and operate the session through the service uniformly.
  2. Tomcat internally uses the session manager to retrieve the session and iterates through all sessions in the context.

Plan 1

Just rewrite the session method.

Plan 2

After finding the source code, I found that it has supported a form similar to traversing sessions in all contexts. First, when obtaining the session, if the cresContext property is true, it will try to traverse whether all contexts have the sessionid when it is not available. If it exists, create your own session object according to the sessionid in this context.

 public HttpSession getSession(boolean create) {

    if (crossContext) {

      // There cannot be a session if no context has been assigned yet
      if (context == null)
        return (null);

      // Return the current session if it exists and is valid
      if (session != null && ()) {
        return (());
      }

      HttpSession other = (false);
      if (create && (other == null)) {
        // First create a session in the first context: the problem is
        // that the top level request is the only one which can 
        // create the cookie safely
        other = (true);
      }
      if (other != null) {
        Session localSession = null;
        try {
          localSession =
            ().findSession(());
          if (localSession != null && !()) {
            localSession = null;
          }
        } catch (IOException e) {
          // Ignore
        }
        if (localSession == null && create) {
          localSession = 
            ().createSession(());
        }
        if (localSession != null) {
          ();
          session = localSession;
          return ();
        }
      }
      return null;

    } else {
      return (create);
    }

  }

When obtaining a cross-application session, context (web application) is obtained by following operations:

().getServletContext().getContext("/app2").getAttribute("att2"); 

This is because the request will get the session object according to the sessionid of the cookies, and it will not be reported that it cannot be found, because a session object has been created based on other sessionids before, and then the getContext operation will get the context of the corresponding url and then perform the session operation.

public ServletContext getContext(String uri) {

    // Validate the format of the specified argument
    if (uri == null || !("/")) {
      return null;
    }

    Context child = null;
    try {
      // Look for an exact match
      Container host = ();
      child = (Context) (uri);

      // Non-running contexts should be ignored.
      if (child != null && !().isAvailable()) {
        child = null;
      }

      // Remove any version information and use the mapper
      if (child == null) {
        int i = ("##");
        if (i > -1) {
          uri = (0, i);
        }
        // Note: This could be more efficient with a dedicated Mapper
        //    method but such an implementation would require some
        //    refactoring of the Mapper to avoid copy/paste of
        //    existing code.
        MessageBytes hostMB = ();
        (());

        MessageBytes pathMB = ();
        (uri);

        MappingData mappingData = new MappingData();
        ((Engine) ()).getService().findConnectors()[0].getMapper().map(
            hostMB, pathMB, null, mappingData);
        child = (Context) ;
      }
    } catch (Throwable t) {
      (t);
      return null;
    }

    if (child == null) {
      return null;
    }

    if (()) {
      // If crossContext is enabled, can always return the context
      return ();
    } else if (child == context) {
      // Can still return the current context
      return ();
    } else {
      // Nothing to return
      return null;
    }
  }

If you have any questions, please leave a message or go to the community of this site to exchange and discuss. Thank you for reading. I hope it can help you. Thank you for your support to this site!