Wir möchten eine funktionierende Anwendung in zwei verschiedene .war
-Dateien aufteilen, um eine App aktualisieren zu können, ohne die andere zu beeinflussen. Jede Webapp hat eine unterschiedliche Benutzeroberfläche, unterschiedliche Benutzer und einen unterschiedlichen Bereitstellungszeitplan.
Der einfachste Pfad scheint die gleiche Sitzung zu teilen. Wenn App A session.setAttribute("foo", "bar")
gesetzt ist, kann App B sie sehen.
Gibt es eine Möglichkeit, den Status HttpSession
für beide Apps in derselben Tomcat-Instanz gemeinsam zu nutzen?
Unsere App läuft auf einem dedizierten Tomcat 5.5. Es werden keine anderen Apps auf derselben Tomcat-Instanz ausgeführt. Daher sind Sicherheitsbedenken hinsichtlich der Sitzungsfreigabe kein Problem. Wir führen mehrere Tomcat-Instanzen aus, aber der Balancer verwendet ständige Sitzungen.
Wenn dies nicht möglich ist oder diese Sitzung teilen eine wirklich schlechte Idee ist, hinterlassen Sie bitte einen Kommentar.
Sie sollten HttpSession nicht freigeben. Sie können jedoch auch andere Objekte freigeben. Sie können beispielsweise ein Objekt über JNDI registrieren und auf das gleiche Objekt in allen Ihren Apps zugreifen (Datenbanken verwenden dies, um Verbindungen zu bündeln).
Zu beachten ist, dass zwei Web-Apps unterschiedliche Klassenladeprogramme verwenden. Wenn Sie Objekte gemeinsam nutzen möchten, müssen sie dieselbe Version der Klasse aus demselben Klassenladeprogramm verwenden (andernfalls erhalten Sie LinkageErrors). Dies bedeutet, dass sie entweder in einen Klassenlader gestellt werden, der von beiden Web-Apps gemeinsam genutzt wird (z. B. Systemklassenpfad) OR, indem die Serialisierung verwendet wird, um das Objekt im richtigen Klassenlader mit der richtigen Version der Klasse effektiv zu entleeren und wiederherzustellen.
Wenn Sie Spring verwenden möchten, gibt es ein Projekt namens Spring Session: https://github.com/spring-projects/spring-session
Zitat: "HttpSession - Ermöglicht das Ersetzen der HttpSession in einem Anwendungscontainer (d. H. Tomcat) auf neutrale Weise."
Wenn die Webapps so eng miteinander verbunden sind, dass sie Objekte gemeinsam nutzen müssen, warum teilen Sie sie dann in zwei Teile auf? Selbst wenn Sie sie einigermaßen unabhängig verwalten, sollte jedes anständige Build-Verwaltungssystem in der Lage sein, eine einzige WAR-Datei für die Bereitstellung zu erstellen.
Eine Lösung wie Aaron schlägt mit JNDI vor, funktioniert jedoch nur, wenn beide Webapps auf demselben Server ausgeführt werden. Wenn die Einheiten eng miteinander verbunden sind und Sie sie trotzdem auf demselben Server ausführen, kann es auch einen einzigen WAR geben
Wenn Sie wirklich wollen, dass sie unabhängig stehen, würde ich den Datenaustausch zwischen beiden ernsthaft prüfen. Im Idealfall möchten Sie, dass sie nur relevante Daten miteinander teilen. Diese Daten können über die Parameter POST (oder GET, wenn dies angemessener ist) hin- und hergegeben werden. Möglicherweise verwenden Sie auch Cookies.
Eine Möglichkeit hierzu ist in diesem Blogbeitrag beschrieben: Sitzungsfreigabe in Apache Tomcat
Zusammenfassung: Fügen Sie emptySessionPath der Connector-Konfiguration und crossContext zum Kontext hinzu
Für Tomcat 8 verwende ich die folgende Konfiguration, um eine Sitzung über 2 Webanwendungen zu teilen:
conf/context.xml
<Context sessionCookiePath="/">
<Valve className="org.Apache.catalina.valves.PersistentValve"/>
<Manager className="org.Apache.catalina.session.PersistentManager">
<Store className="org.Apache.catalina.session.FileStore" directory="${catalina.base}/temp/sessions"/>
</Manager>
...
</Context>
Ich setze dieselbe einfache Webanwendung zweimal ein log.war und log2.war :
/log
/log2
Ich kann mich jetzt bei /log
anmelden und den Benutzer in /log2
anzeigen lassen. Dies funktioniert nicht mit der Tomcat-Standardkonfiguration.
Der Sitzungswert wird gesetzt und gelesen:
HttpSession session=request.getSession();
session.setAttribute("name",name);
HttpSession session=request.getSession(false);
String name=(String)session.getAttribute("name");
Ich habe dieses Projekt als Beispiel verwendet: https://www.javatpoint.com/servlet-http-session-login-and-logout-example
Die meisten Beispiele/Lösungen verwenden eine In-Memory-Datenbank, die mehr Einrichtungsarbeit erfordert:
Sie können dies tun, indem Sie den Servlet-Kontext von Ihrem Kontextstammverzeichnis nehmen.
Zum Abrufen von Variablen.
request.getSession().getServletContext().getContext("/{applicationContextRoot}").getAttribute(variableName)
Zum Einstellen der Variablen:
request.getSession().getServletContext().getContext("/{applicationContextRoot}").setAttribute(variableName,variableValue)
Hinweis: Beide Anwendungen sollten auf demselben Server bereitgestellt werden.
Bitte lassen Sie mich wissen, wenn Sie ein Problem finden
Tomcat 8: Ich musste folgendes tun: <Context crossContext="true" sessionCookiePath="/">
in conf/context.xml
weitere Details zu den Konfigurationsattributen hier
und dann, um den Wert einzustellen (wie @ Qazis Antwort):
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.setAttribute(variableName,variableValue)
um den Wert zu erhalten:
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.getAttribute("user");
Ich habe Session State Server für Tomcat mit Python entwickelt.
Aus diesem Grund muss ich den bereits erstellten Code zum Erstellen/Zugreifen auf und Zerstören von Sitzungen nicht ändern. Da es einen separaten Server/Dienst gibt, der die Sitzung behandelt und speichert, ist kein Master-Cluster erforderlich. In diesem Fall gibt es keine Sitzungsreplikation (wie beim Tomcat-Clustering), sondern es ist eine Sitzungsfreigabe zwischen Web-Farming.