web-dev-qa-db-fra.com

Enregistrement des données dans la session dans JSF

Je suis nouveau dans le monde de J (2) EE et du développement d'applications Web, mais je me fraye un chemin rapidement et j'apprends beaucoup. Chaque jour est pour moi un fantastique voyage de découverte.

Je travaille actuellement sur un projet dans lequel j'utilise Visual JSF Woodstock sur Glassfish v2. Je suis également assez nouveau pour JSF.

Il y a des moments où j'ai besoin de sauvegarder certains objets (disons MyObject par exemple) entre les requêtes. Et d'après ce que j'ai lu et compris jusqu'à présent, je dois utiliser des sessions pour enregistrer ces objets entre différentes demandes. Jusqu'ici tout va bien.

Exactement comment faire cela, c'est là que réside ma préoccupation. Je sais que dans JSP, vous pouvez utiliser la session.setAttribute("myObj", myObject) qui sauverait l'objet côté client en utilisant des cookies ou des réécritures d'URL ou des variables de formulaire cachées.

D'un autre côté, dans JSF, j'utilise des beans de portée Session, par exemple SessionBean1, par exemple, et j'enregistre des objets en tant que propriétés SessionBean1 (par exemple SessionBean1.setSomeOjb(myObj)). Est-ce la bonne façon de procéder?

Je suppose que le faire de cette façon entraînera une utilisation accrue de la mémoire à la fin du serveur puisque chaque demande créera une nouvelle instance du bean à portée de session, SessionBean1 plus la mémoire utilisée par les instances myObject enregistrées dans SessionBean1.

J'ai lu que vous pouvez utiliser FacesContext.getExternalContext().getSession/getSessionMap() qui sauverait les variables de session côté client.

Alors, quelle méthode suggéreriez-vous que j'utilise - le bean de portée de session ou la map de session pour enregistrer les objets pour l'accès entre les demandes d'une session?

Merci.

23
SibzTer

En général Java EE Web Apps a tendance à ne pas s'attendre à enregistrer le côté client des données de session. des empreintes qui peuvent entraîner des problèmes importants de ressources et de performances, et peuvent être particulièrement présentes dans des environnements en cluster.

J'aimerais savoir où tu vois

J'ai lu que vous pouvez utiliser FacesContext.getExternalContext (). GetSession/getSessionMap () qui enregistrerait les variables de session côté client.

Je crois (corrigez-moi sur ce point) que cela donne simplement accès à l'objet HttpSession, sur lequel vous pouvez ensuite utiliser le même

 session.setAttribute("myObj", myObject)

cela ne renvoie pas en soi l'objet au client, il est conservé sur le serveur et saisi par un identifiant de session, généralement passé dans un cookie.

Il existe maintenant deux autres techniques: vous pouvez explicitement choisir de placer des données dans un cookie de votre propre fabrication - les API de servlet auxquelles vous pouvez accéder à partir de JSF ou JSP vous le permettraient, ou vous pouvez utiliser des champs masqués sur vos formulaires, et passez donc une ou deux données de session.

Mais considérez ceci. Une règle d'or sur l'App Server que j'utilise est que la HttpSession de l'ordre de 1k à 4k n'a pas tendance à être un problème. Plus grand que cela (et j'ai vu des sessions mesurées en mégaoctets) stressent l'infrastructure. Si vous étiez préoccupé par des sessions de cette taille, vous attendriez-vous à renvoyer des mégaoctets de données dans un cookie ou un champ caché au navigateur à chaque demande? Même 1k-2k est probablement un peu gros.

Donc recommandations:

  1. Rester simple. Utilisez l'API de session ou sa manifestation JSF.

  2. Gardez la quantité de données dans la session sous contrôle.

Ajouté en réponse à une question sur le clustering:

En règle générale, dans un environnement en cluster, nous avons une affinité de session, de sorte que les demandes sont renvoyées au même membre de cluster. Cependant, nous devons toujours considérer le cas (peut-être si un membre du cluster échoue) lorsque la demande est envoyée à un autre serveur.

Certains fournisseurs d'App Server offrent une réplication de session, soit via une communication directe entre les serveurs, soit en conservant la session dans une base de données - il y a évidemment des frais généraux ici, donc parfois, pour les sessions de faible valeur, nous acceptons simplement la perte de session en cas d'échec.

Il existe un argument selon lequel si les données de session ont une valeur élevée, elles doivent être conservées par l'application, ce sont en fait des données commerciales et doivent être traitées comme telles. De plus en plus, des bases de données NOSQL telles que Cloudant ou MongoDb sont utilisées pour cela. Dans ce cas, nous pouvons considérer la session HTTP comme un cache, sachant que les données de session peuvent être récupérées en cas d'erreur.

Je dirais donc qu'un panier pourrait avoir une valeur considérable pour l'entreprise; il représente l'accumulation réfléchie des clients sur lesquels ils veulent dépenser de l'argent. Il faut donc persister, plutôt que de simplement le maintenir dans la session. Une fois que nous décidons de le persister, nous constatons qu'il conduit à d'autres scénarios intéressants tels qu'une expérience consolidée sur de nombreux appareils clients. Le client commence ses achats chez lui sur un ordinateur de bureau, mais termine l'achat en ligne.

Donc, un autre principe:

3). N'utilisez pas trop la session HTTP simplement parce qu'elle est là. Tenez compte de la valeur commerciale des données et déterminez si elles doivent être conservées.

22
djna

Je travaille sur un projet de l'université avec mes collègues, c'est un web comme GoogleImage Labeler. Eh bien, nous avons donc un UserController, avec ses méthodes de connexion, déconnexion, etc ... et nous étendons la session comme ceci:

@ManagedBean(name = "userController")
@SessionScoped

Ok, c'est ce que l'assistant de NetBeans crée pour vous.

Notre façon de créer et de gérer la session est:

Lors de la méthode d'enregistrement (dans laquelle nous utilisons les attributs du formulaire dans le XHTML ...), nous persistons l'utilisateur dans la base de données, puis nous ajoutons les valeurs dans la session:

FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("user", current);

Où "actuel" est un utilisateur (l'utilisateur connecté, bien sûr). Nous avons la même chose au méthode de connexion.

Au méthode de déconnexion nous avons:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

J'espère que ceci vous aide.

14
Carlos Vega

Alors, quelle méthode suggéreriez-vous que j'utilise - le bean à portée de session ou la map de session pour enregistrer les objets pour l'accès entre les demandes de session?

Ces deux éléments stockent les données exactement au même endroit.

<managed-bean>
  <managed-bean-class>foo.Bar</managed-bean-class>
  <managed-bean-name>bar</managed-bean-name>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Une fois référencé dans une expression, vous pouvez rechercher "bar" par programmation via le contexte externe .

Pour info: en JSF2, la déclaration peut être supprimée et remplacée par des annotations:

@ManagedBean(name="bar") @SessionScoped
public class Bar {
...
2
McDowell