Comment choisir la bonne portée de bean?


Réponses:


485

introduction

Il représente la portée (la durée de vie) du bean. Ceci est plus facile à comprendre si vous êtes familiarisé avec le fonctionnement «sous les couvertures» d'une application Web de servlet de base: comment fonctionnent les servlets? Instanciation, sessions, variables partagées et multithreading .


@Request/View/Flow/Session/ApplicationScoped

Un @RequestScopedbean vit aussi longtemps qu'un seul cycle de demande-réponse HTTP (notez qu'une demande Ajax compte aussi comme une seule demande HTTP). Un @ViewScopedbean vit tant que vous interagissez avec la même vue JSF par des publications qui appellent des méthodes d'action renvoyant null/ voidsans navigation / redirection. Un @FlowScopedbean vit tant que vous parcourez la collection spécifiée de vues enregistrées dans le fichier de configuration de flux. Un @SessionScopedbean vit aussi longtemps que la session HTTP établie. Un @ApplicationScopedbean vit aussi longtemps que l'application Web s'exécute. Notez que le CDI @Modelest fondamentalement un stéréotype pour @Named @RequestScoped, donc les mêmes règles s'appliquent.

L'étendue à choisir dépend uniquement des données (l'état) que le bean détient et représente. Utilisez @RequestScopedpour les formulaires / présentations simples et non ajax. À utiliser @ViewScopedpour les vues dynamiques riches en ajax (validation basée sur ajax, rendu, boîtes de dialogue, etc.). À utiliser @FlowScopedpour le modèle "assistant" ("questionnaire") de collecte des données d'entrée réparties sur plusieurs pages. Utilisation @SessionScopedpour les données spécifiques au client, telles que l'utilisateur connecté et les préférences de l'utilisateur (langue, etc.). Utilisation@ApplicationScoped pour les données / constantes à l'échelle de l'application, telles que les listes déroulantes qui sont les mêmes pour tout le monde, ou les beans gérés sans variables d'instance et n'ayant que des méthodes.

L'utilisation abusive d'un @ApplicationScopedbean pour les données de portée de session / vue / demande le ferait être partagé entre tous les utilisateurs, de sorte que n'importe qui d'autre puisse voir les données les uns des autres, ce qui est tout simplement faux. L'utilisation abusive d'un @SessionScopedbean pour les données de portée vue / demande le ferait être partagé entre tous les onglets / fenêtres dans une seule session de navigateur, de sorte que l'utilisateur final peut rencontrer des incohérences lors de l'interaction avec chaque vue après avoir basculé entre les onglets, ce qui est mauvais pour l'expérience utilisateur. L'utilisation abusive d'un @RequestScopedbean pour les données de portée de vue entraînerait la réinitialisation des données de portée de vue par défaut sur chaque publication (ajax), provoquant éventuellement des formulaires non fonctionnels ( voir également les points 4 et 5 ici ). Utilisation abusive d'un @ViewScopedbean pour des données de portée de demande, de session ou d'application et utilisation abusive d'un@SessionScoped Le bean pour les données de portée d'application n'affecte pas le client, mais il occupe inutilement la mémoire du serveur et est tout simplement inefficace.

Notez que la portée ne doit pas être choisie en fonction des implications en termes de performances, à moins que vous n'ayez vraiment une faible empreinte mémoire et que vous souhaitiez devenir complètement sans état; vous auriez besoin d'utiliser exclusivement des @RequestScopedbeans et de jouer avec les paramètres de requête pour maintenir l'état du client. Notez également que lorsque vous avez une seule page JSF avec des données de portée différente, il est parfaitement valide de les placer dans des beans de sauvegarde distincts dans une étendue correspondant à l'étendue des données. Les beans peuvent simplement accéder les uns aux autres via @ManagedPropertyen cas de beans gérés JSF ou @Injecten cas de beans gérés CDI.

Voir également:


@CustomScoped/NoneScoped/Dependent

Ce n'est pas mentionné dans votre question, mais (hérité) JSF prend également en charge @CustomScopedet @NoneScoped, qui sont rarement utilisés dans le monde réel. Le @CustomScopeddoit référencer une Map<K, Bean>implémentation personnalisée dans une portée plus large qui a remplacé Map#put()et / ou Map#get()afin d'avoir un contrôle plus fin sur la création et / ou la destruction du bean.

Le JSF @NoneScopedet le CDI @Dependentvivent essentiellement aussi longtemps qu'une seule évaluation EL sur le bean. Imaginez un formulaire de connexion avec deux champs de saisie faisant référence à une propriété de bean et un bouton de commande faisant référence à une action de bean, donc avec au total trois expressions EL, puis en fait trois instances seront créées. Un avec le nom d'utilisateur défini, un avec le mot de passe défini et un sur lequel l'action est invoquée. Vous souhaitez normalement utiliser cette étendue uniquement sur les beans qui doivent vivre aussi longtemps que le bean où il est injecté. Donc, si un @NoneScopedou @Dependentest injecté dans un @SessionScoped, il vivra aussi longtemps que le @SessionScopedharicot.

Voir également:


Portée Flash

Comme précédemment, JSF prend également en charge la portée flash. Il est soutenu par un cookie vivant court qui est associé à une entrée de données dans la portée de la session. Avant la redirection, un cookie sera défini sur la réponse HTTP avec une valeur qui est uniquement associée à l'entrée de données dans la portée de la session. Après la redirection, la présence du cookie de portée flash sera vérifiée et l'entrée de données associée au cookie sera supprimée de la portée de la session et placée dans la portée de la demande de la demande redirigée. Enfin, le cookie sera supprimé de la réponse HTTP. De cette façon, la demande redirigée a accès aux données de portée de demande qui ont été préparées dans la demande initiale.

Ce n'est en fait pas disponible en tant que portée de bean géré, c'est-à-dire qu'il n'y a rien de tel @FlashScoped. La portée flash est uniquement disponible sous forme de carte via les ExternalContext#getFlash()beans gérés et #{flash}EL.

Voir également:


4
Je pense qu'une référence à votre réponse à la question " Comment et quand un bean de portée de vue est détruit dans JSF? " Est pertinente ici.
Lii

3
@Cold: c'est une ancienne portée CDI et dans JSF 2.2 substitué par @FlowScoped(pas besoin de le démarrer / l'arrêter manuellement).
BalusC

1
Et DeltaSpike a également ViewAccesscopedetWindowScoped
Kukeltje

@BalusC, je pense qu'il y a un problème avec le ViewScopedbean dans MyFaces 2.2. Je suis actuellement confronté à un problème avec le ViewScopedbean et l'Ajax, que j'ai publié ici . Dans MyFaces JIRA, il y a aussi une discussion sur ce sujet.
Tapas Bose

CDI définit quatre étendues intégrées: @RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped pourquoi les étendues que vous décrivez sont différentes?
Hosein Aqajani

122

Depuis JSF 2.3, toutes les étendues de bean définies dans package javax.faces.beanpackage ont été déconseillées pour aligner les étendues avec CDI. De plus, ils ne sont applicables que si votre bean utilise des @ManagedBeanannotations. Si vous utilisez des versions JSF inférieures à 2.3, reportez-vous à la réponse héritée à la fin.


De JSF 2.3 voici des étendues qui peuvent être utilisées sur les Jing Backing Beans:

1@javax.enterprise.context.ApplicationScoped .: L'étendue de l'application persiste pendant toute la durée de l'application Web. Cette portée est partagée entre toutes les demandes et toutes les sessions. Ceci est utile lorsque vous disposez de données pour l'ensemble de l'application.

2@javax.enterprise.context.SessionScoped .: La portée de la session persiste à partir du moment où une session est établie jusqu'à la fin de la session. Le contexte de session est partagé entre toutes les demandes qui se produisent dans la même session HTTP. Ceci est utile lorsque vous ne souhaitez pas enregistrer de données pour un client spécifique pour une session particulière.

3@javax.enterprise.context.ConversationScoped .: La portée de la conversation persiste aussi longtemps que le bean vit. La portée propose 2 méthodes: Conversation.begin()et Conversation.end(). Ces méthodes doivent être appelées explicitement, soit pour démarrer soit pour mettre fin à la vie d'un bean.

4@javax.enterprise.context.RequestScoped .: La portée de la demande est de courte durée. Il démarre lorsqu'une demande HTTP est soumise et se termine une fois la réponse renvoyée au client. Si vous placez un bean géré dans la portée de la demande, une nouvelle instance est créée avec chaque demande. Il vaut la peine d'envisager la portée de la demande si vous êtes préoccupé par le coût du stockage de la portée de la session.

5@javax.faces.flow.FlowScoped .: La portée du Flow persiste aussi longtemps que le Flow dure. Un flux peut être défini comme un ensemble contenu de pages (ou vues) qui définissent une unité d'oeuvre. Le flux délimité est actif tant que l'utilisateur navigue dans le flux.

6@javax.faces.view.ViewScoped .: Un bean dans la portée de la vue persiste pendant que la même page JSF est ré-affichée. Dès que l'utilisateur accède à une autre page, le bean sort du cadre.


La réponse héritée suivante applique la version JSF avant 2.3

Depuis JSF 2.x, il existe 4 étendues de bean:

  • @SessionScoped
  • @RequestScoped
  • @ApplicationScoped
  • @ViewScoped

Étendue de la session: l' étendue de la session persiste à partir du moment où une session est établie jusqu'à la fin de la session. Une session se termine si l'application Web appelle la méthode invalidate sur l'objet HttpSession, ou si elle expire.

RequestScope: la portée de la demande est de courte durée. Il démarre lorsqu'une demande HTTP est soumise et se termine une fois la réponse renvoyée au client. Si vous placez un bean géré dans la portée de la demande, une nouvelle instance est créée avec chaque demande. Il vaut la peine d'envisager la portée de la demande si vous êtes préoccupé par le coût du stockage de la portée de la session.

ApplicationScope: la portée de l'application persiste pendant toute la durée de l'application Web. Cette portée est partagée entre toutes les demandes et toutes les sessions. Vous placez les beans gérés dans la portée de l'application si un seul bean doit être partagé entre toutes les instances d'une application Web. Le bean est construit lorsqu'il est demandé pour la première fois par n'importe quel utilisateur de l'application, et il reste actif jusqu'à ce que l'application Web soit supprimée du serveur d'applications.

ViewScope: la portée de la vue a été ajoutée dans JSF 2.0. Un bean dans la portée de la vue persiste pendant que la même page JSF est ré-affichée. (La spécification JSF utilise la vue terminologique pour une page JSF.) Dès que l'utilisateur accède à une autre page, le bean sort du domaine.

Choisissez la portée que vous avez basée sur votre condition.

Source: Core Java Server Faces 3rd Edition par David Geary & Cay Horstmann [Page no. 51 - 54] entrez la description de l'image ici


Pourriez-vous préciser, que voulez-vous dire par «la méthode invalidate sur l'objet HttpSession»: invalidate()méthode ou méthode non valide?
Alexander Pozdneev

1
Un peu vieux et peut-être en retard pour la réponse, mais pour clarifier les choses: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();être invoqué dans votre "bean de déconnexion" est ce qu'il veut dire.
Roland

1
c'est devenu une réponse héritée, en ce moment il y a 8 portées
Ewoks

@KishorPrakash: il y a 6 mois maintenant. ;-)
Kukeltje

@Kukeltje: Désolé, j'y suis.
Kishor Prakash
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.