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
- Extract the session into a session service and operate the session through the service uniformly.
- 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!