Nous souhaitons diviser une application en cours de travail en deux fichiers .war
différents afin de pouvoir mettre à jour une application sans affecter l'autre. Chaque application Web aura une interface utilisateur différente, des utilisateurs différents et une planification de déploiement différente.
Le chemin le plus simple semble partager la même session. Par conséquent, si l'application A est définie par session.setAttribute("foo", "bar")
, l'application B pourra la voir.
Existe-t-il un moyen de partager l'état HttpSession
pour les deux applications dans la même instance Tomcat?
Notre application est exécutée sur un Tomcat 5.5 dédié. Aucune autre application ne s'exécute sur la même instance de Tomcat. Par conséquent, les problèmes de sécurité liés au partage de session ne posent aucun problème. Nous exécutons plusieurs instances de Tomcat, mais l'équilibreur utilise des sessions persistantes.
Si ce n'est pas possible ou que ce partage de session est une très mauvaise idée, veuillez laisser un commentaire.
Vous ne devriez pas partager HttpSession; mais vous pouvez partager d'autres objets. Par exemple, vous pouvez enregistrer un objet via JNDI et accéder au même objet dans toutes vos applications (les bases de données l'utilisent pour regrouper les connexions).
Une chose à prendre en compte est que deux applications Web utiliseront des chargeurs de classe différents. Si vous souhaitez partager des objets, ils doivent utiliser la même version de la classe à partir du même chargeur de classes (sinon vous obtiendrez LinkageErrors). Cela signifie soit de les placer dans un chargeur de classe partagé par les deux applications Web (chemin de classe système, par exemple) OR en utilisant la sérialisation pour drainer et reconstituer efficacement l'objet dans le chargeur de classe approprié avec la version correcte de la classe.
Si vous voulez utiliser Spring, il existe un projet appelé Spring Session: https://github.com/spring-projects/spring-session
Quotation: "HttpSession - permet de remplacer HttpSession dans un conteneur d’application (c’est-à-dire Tomcat) de manière neutre"
Si les applications Web to sont si étroitement associées qu'elles doivent partager des objets, pourquoi la divisez-vous en deux? Même si vous les gérez de manière assez indépendante, tout système de gestion de build décent devrait pouvoir créer un seul fichier WAR à déployer.
Une solution comme celle suggérée par Aaron avec JNDI fonctionnera, mais uniquement si les deux applications Web s'exécutent sur le même serveur. Si les unités sont étroitement couplées et que vous allez l'exécuter de toute façon sur le même serveur ... vous pourriez aussi bien avoir un seul WAR.
Si vous voulez vraiment qu'ils agissent de manière indépendante, j'examinerai sérieusement l'échange de données entre les deux. Idéalement, vous voudriez qu'ils ne partagent que les données pertinentes les uns avec les autres. Ces données peuvent être échangées via les paramètres POST (ou GET si cela convient mieux), vous pourriez même envisager d'utiliser des cookies.
Une façon de faire est décrite dans cet article de blog: Partage de session dans Apache Tomcat
Résumé: ajoutez emptySessionPath à la configuration du connecteur et crossContext au contexte
Pour Tomcat 8, j'utilise la configuration suivante pour partager une session sur 2 applications Web:
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>
Je déploie deux fois la même application Web simple log.war et log2.war :
/log
/log2
Je peux maintenant me connecter à /log
et avoir l’utilisateur affiché dans /log2
, cela ne fonctionne pas avec la configuration par défaut de Tomcat.
La valeur de session est définie et lue:
HttpSession session=request.getSession();
session.setAttribute("name",name);
HttpSession session=request.getSession(false);
String name=(String)session.getAttribute("name");
J'ai utilisé ce projet comme exemple: https://www.javatpoint.com/servlet-http-session-login-and-logout-example
La plupart des exemples/solutions utilisent une base de données en mémoire qui nécessite davantage de travail d'installation:
Vous pouvez le faire en prenant le contexte de servlet par votre racine de contexte.
Pour récupérer variable.
request.getSession().getServletContext().getContext("/{applicationContextRoot}").getAttribute(variableName)
Pour la variable de réglage:
request.getSession().getServletContext().getContext("/{applicationContextRoot}").setAttribute(variableName,variableValue)
Remarque: Les deux applications doivent être déployées sur le même serveur.
Pls laissez-moi savoir si vous trouvez un problème
Tomcat 8: Je devais faire: <Context crossContext="true" sessionCookiePath="/">
dans conf/context.xml
plus de détails sur les attributs de configuration ici
puis pour définir la valeur (comme la réponse de @ Qazi):
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.setAttribute(variableName,variableValue)
pour obtenir la valeur:
ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.getAttribute("user");
J'ai développé serveur d'état de session pour Tomcat à l'aide de python.
Pour cette raison, je n'ai pas besoin de changer le code déjà écrit pour créer/accéder et détruire une session. De plus, comme il existe un serveur/service distinct qui gère et stocke la session, aucun cluster maître n'est nécessaire. Il n'y a pas de réplication de session (comme dans le clustering Tomcat) dans ce cas, il s'agit plutôt d'un partage de session entre une exploitation Web.