J'ai remarqué qu'il existe différents champs de haricots comme:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
Quel est le but de chacun? Comment choisir un champ approprié pour mon haricot?
Il représente la portée (la durée de vie) du haricot. Cela est plus facile à comprendre si vous connaissez le travail "sous la couverture" 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 bean @RequestScoped
vit aussi longtemps qu'un seul cycle de requête-réponse HTTP (notez qu'une requête Ajax compte également comme une requête HTTP unique). Un bean @ViewScoped
vit tant que vous interagissez avec la même vue JSF par des publications qui appellent des méthodes d'action retournant null
/void
sans navigation/redirection . Un bean @FlowScoped
est maintenu tant que vous naviguez dans la collection de vues spécifiée enregistrée dans le fichier de configuration du flux. Un bean @SessionScoped
est conservé aussi longtemps que la session HTTP établie. Un bean @ApplicationScoped
reste actif aussi longtemps que l'application Web s'exécute. Notez que le CDI _@Model
_ est fondamentalement un stéréotype pour _@Named @RequestScoped
_, de sorte que les mêmes règles s'appliquent.
La portée à choisir dépend uniquement des données (l'état) que le bean détient et représente. Utilisez _@RequestScoped
_ pour les formulaires/présentations simples et non ajax. Utilisez _@ViewScoped
_ pour les vues dynamiques enrichies avec ajax (validation, rendu, boîtes de dialogue, etc.). Utilisez _@FlowScoped
_ pour le modèle "assistant" ("questionnaire") de collecte de données d'entrée réparties sur plusieurs pages. Utilisez _@SessionScoped
_ pour les données spécifiques au client, telles que l'utilisateur connecté et ses préférences utilisateur (langue, etc.). Utilisez _@ApplicationScoped
_ pour les données/constantes à l'échelle de l'application, telles que les listes déroulantes identiques pour tout le monde, ou les beans gérés sans variables d'instance et n'ayant que des méthodes.
Abuser d'un bean _@ApplicationScoped
_ pour des données de portée de session/vue/demande permettrait de les partager avec tous les utilisateurs, de sorte que tout autre utilisateur puisse voir les données de l'autre qui sont tout simplement fausses. Abuser d’un bean _@SessionScoped
_ pour des données étendues de vue/demande permettrait de les partager entre tous les onglets/fenêtres d’une même session de navigateur. Par conséquent, l’utilisateur final pourrait avoir des incohérences lorsqu’il interagirait avec chaque vue après avoir basculé entre les onglets expérience utilisateur. Si vous abusez d'un bean _@RequestScoped
_ pour des données avec vue, les données de vue doivent être réinitialisées sur chaque publication (ajax) par défaut, ce qui peut entraîner l'apparition de formulaires non fonctionnels ( voir également les points 4 et 5 ici) =). Abuser d'un bean _@ViewScoped
_ pour des données de portée de demande, de session ou d'application, et d'abuser d'un bean _@SessionScoped
_ pour des données de portée d'application, n'affecte pas le client, mais occupe inutilement la mémoire du serveur et est totalement inefficace.
Notez que la portée ne devrait plutôt pas être choisie en fonction des implications en termes de performances, sauf si vous réellement avez une faible empreinte de mémoire et souhaitez aller complètement sans état; vous devez utiliser exclusivement _@RequestScoped
_ beans et manipuler les paramètres de requête pour conserver 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 correct de les placer dans des beans de sauvegarde séparés dans une étendue correspondant à celle des données. Les beans peuvent simplement accéder les uns aux autres via _@ManagedProperty
_ en cas de beans gérés par JSF ou _@Inject
_ en cas de beans gérés par CDI.
@CustomScoped/NoneScoped/Dependent
_Ce n'est pas mentionné dans votre question, mais (ancien) JSF prend également en charge @CustomScoped
et @NoneScoped
, qui sont rarement utilisés dans le monde réel. _@CustomScoped
_ doit faire référence à une implémentation personnalisée _Map<K, Bean>
_ dans une portée plus large qui a surchargé Map#put()
et/ou Map#get()
afin d’avoir un contrôle plus fin sur la création et/ou la destruction de beans.
Le JSF _@NoneScoped
_ et le CDI @Dependent
vivent essentiellement aussi longtemps qu'une seule évaluation EL sur le haricot. 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. Ainsi, avec trois expressions EL au total, trois instances seront effectivement créées. L'une avec le nom d'utilisateur défini, l'autre avec le mot de passe défini et l'autre sur lequel l'action est appelée. Vous voulez normalement utiliser cette étendue uniquement sur les haricots qui doivent vivre aussi longtemps que le haricot où il est injecté. Ainsi, si un _@NoneScoped
_ ou un _@Dependent
_ est injecté dans un _@SessionScoped
_, il vivra aussi longtemps que le bean _@SessionScoped
_.
En dernier lieu, JSF prend également en charge la portée flash. Il est accompagné d'un cookie à vie courte associé à une entrée de données dans l'étendue de la session. Avant la redirection, un cookie sera défini sur la réponse HTTP avec une valeur associée de manière unique à la saisie de données dans l'étendue de la session. Après la redirection, la présence du cookie Flash scope sera vérifiée et la saisie de données associée au cookie sera supprimée de la session et placée dans la portée de la requête 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 la portée de la demande qui ont été préparées dans la demande initiale.
Ceci n’est en fait pas disponible en tant qu’étendue de bean géré, c’est-à-dire que _@FlashScoped
_ n’existe pas. La portée flash est uniquement disponible sous forme de carte via ExternalContext#getFlash()
dans les beans gérés et _#{flash}
_ dans EL.
A partir de JSF 2.x, il y a 4 étendues de haricots:
- @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 arrive à expiration.
RequestScope: La portée de la requête est de courte durée. Il commence lorsqu'une demande HTTP est soumise et se termine lorsque la réponse est 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 est utile d’envisager l’étendue de la demande si vous vous inquiétez du coût de son stockage.
ApplicationScope: La portée de l'application persiste pendant toute la durée de l'application Web. Cette étendue est partagée entre toutes les demandes et toutes les sessions. Vous placez des beans gérés dans l'étendue de l'application si un seul bean doit être partagé entre toutes les instances d'une application Web. Le bean est construit à la demande initiale d'un utilisateur de l'application et reste actif jusqu'à la suppression de l'application Web 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 tant que la même page JSF est à nouveau affichée. (La spécification JSF utilise la vue de terme pour une page JSF.) Dès que l'utilisateur accède à une page différente, le bean sort de la portée.
Choisissez la portée que vous avez basée sur vos besoins.
Source: Core Java Server Faces 3e édition par David Geary & Cay Horstmann [Page no. 51 - 54]