Il y a beaucoup de matériaux qui différencient value
attribut et binding
attribut dans JSF.
Je suis intéressé par la façon dont les deux approches diffèrent l'une de l'autre. Donné:
public class User {
private String name;
private UICommand link;
// Getters and setters omitted.
}
<h:form>
<h:commandLink binding="#{user.link}" value="#{user.name}" />
</h:form>
C'est assez simple ce qui se passe lorsqu'un attribut value
est spécifié. Le getter s'exécute pour renvoyer la valeur de la propriété name
du bean User
. La valeur est imprimée en sortie HTML.
Mais je ne comprenais pas comment binding
fonctionnait. Comment le code HTML généré maintient-il une liaison avec la propriété link
du bean User
?
Ci-dessous se trouve la partie pertinente de la sortie générée après embellissement manuel et commentaire (notez que l'identifiant j_id_jsp_1847466274_1
a été généré automatiquement et qu’il existe deux widgets d’entrée cachés). J'utilise JSF RI de Sun, version 1.2.
<form action="/TestJSF/main.jsf" enctype="application/x-www-form-urlencoded"
id="j_id_jsp_1847466274_1" method="post" name="j_id_jsp_1847466274_1">
<input name="j_id_jsp_1847466274_1" type="hidden" value="j_id_jsp_1847466274_1">
<a href="#" onclick="...">Name</a>
<input autocomplete="off" id="javax.faces.ViewState" name="javax.faces.ViewState"
type="hidden" value="-908991273579182886:-7278326187282654551">
</form>
Où le binding
est-il stocké ici?
Quand une vue JSF (fichier Facelets/JSP) est construite/restaurée, une arborescence de composants JSF est générée. À ce moment, les heure de création de la vue , tous les attributs binding
sont évalués ( avec id
attributs et gestionnaires de balises tels que JSTL ). Lorsque le composant JSF doit être créé avant d'être ajouté à l'arborescence des composants, JSF vérifie si l'attribut binding
renvoie un composant précréé (c'est-à-dire non -null
) et, le cas échéant, utilisez-le. . Si ce n'est pas déjà créé, JSF créera automatiquement le composant "de la manière habituelle" et invoquera le créateur derrière l'attribut binding
avec l'argument l'instance de composant créée automatiquement.
Dans les effets, il lie une référence de l'occurrence de composant dans l'arbre de composants à une variable étendue. Ces informations ne sont en aucun cas visibles dans la représentation HTML générée du composant lui-même. Ces informations ne sont en aucun cas pertinentes pour la sortie HTML générée. Lorsque le formulaire est soumis et que la vue est restaurée, l'arborescence des composants JSF est simplement reconstruite à partir de zéro et tous les attributs binding
seront simplement réévalués comme décrit dans le paragraphe ci-dessus. Une fois l'arborescence des composants recréée, JSF restaure l'état d'affichage JSF dans l'arborescence des composants.
Il est important de savoir et de comprendre que les instances de composant concret sont effectivement limitées à la demande. Elles sont nouvellement créées à chaque demande et leurs propriétés sont remplies avec les valeurs de l'état d'affichage JSF pendant la phase d'affichage de restauration. Donc, si vous liez le composant à une propriété d'un bean de support, le bean de support ne devrait absolument pas être dans une portée plus large que celle de la requête. Voir aussi spécitication JSF 2. chapitre 3.1.5:
3.1.5 Liaisons de composants
...
Les liaisons de composants sont souvent utilisées avec des JavaBeans instanciés dynamiquement via la fonction de création de beans gérés (voir Section 5.8.1 "VariableResolver et le VariableResolver par défaut"). Il est vivement recommandé aux développeurs d'applications de placer les beans gérés pointés par des expressions de liaison de composant dans l'étendue "request". la portée de l'application nécessiterait la sécurité des threads, car les instances UIComponent dépendent de l'exécution à l'intérieur d'un seul thread. Il y a également des impacts potentiellement négatifs sur la gestion de la mémoire lors du placement d'une liaison de composant dans l'étendue "session".
Sinon, les occurrences de composant sont partagées entre plusieurs requêtes, ce qui peut entraîner des erreurs " ID de composant en double " et des comportements "étranges", car les validateurs, les convertisseurs et les écouteurs déclarés dans la vue sont rattachés à l'instance de composant existante. de demandes précédentes. Les symptômes sont clairs: ils sont exécutés plusieurs fois, une fois de plus avec chaque demande dans la même étendue que celle à laquelle le composant est lié.
Et, sous une charge importante (c'est-à-dire lorsque plusieurs requêtes HTTP différentes (threads) accèdent et manipulent la même instance de composant en même temps), vous pouvez être confronté tôt ou tard à un blocage d'application, par exemple. Stuck thread à UIComponent.popComponentFromEL , ou Java Threads à 100% d'utilisation du processeur à l'aide de richfaces UIDataAdaptorBase et de son HashMap interne , ou même de "étranges" IndexOutOfBoundsException
ou ConcurrentModificationException
venant directement du code source de l'implémentation JSF alors que JSF est occupé à sauvegarder ou à restaurer l'état d'affichage (c'est-à-dire que la trace de la pile indique les méthodes saveState()
ou restoreState()
, etc.).
binding
sur une propriété de bean est une mauvaise pratiqueQuoi qu'il en soit, en utilisant binding
de cette manière, la liaison d'une instance de composant entière à une propriété de bean, même sur un bean étendu de requête, constitue dans JSF 2.x un cas d'utilisation plutôt rare et ne constitue généralement pas la meilleure pratique. Cela indique une odeur de design. Vous déclarez normalement des composants dans la vue et associez leurs attributs d'exécution tels que value
, et peut-être d'autres tels que styleClass
, disabled
, rendered
, etc., à la normale propriétés du haricot. Ensuite, vous manipulez exactement la propriété de bean souhaitée au lieu de saisir tout le composant et d’appeler la méthode setter associée à l’attribut.
Dans les cas où un composant doit être "construit dynamiquement" sur la base d'un modèle statique, mieux vaut utiliser voir les étiquettes de temps de construction telles que JSTL , si nécessaire dans un fichier de balise , au lieu de createComponent()
, new SomeComponent()
, getChildren().add()
et tout le reste. Voir aussi Comment refactoriser un extrait de code JSP ancien en un équivalent JSF?
Ou, si un composant doit être "rendu dynamiquement" sur la base d'un modèle dynamique, utilisez simplement un composant itérateur (<ui:repeat>
, <h:dataTable>
, etc). Voir aussi Comment ajouter dynamiquement des composants JSF .
Les composants composites sont une histoire complètement différente. C'est tout à fait légitime de lier des composants à l'intérieur d'un <cc:implementation>
au composant de support (c’est-à-dire au composant identifié par <cc:interface componentType>
. Voir aussi a.o. Split Java.util.Date sur deux champs h: inputText représentant l'heure et la minute avec f: convertDateTime et Comment implémenter une liste dynamique avec un composant composite JSF 2.0?
binding
dans la portée localeCependant, vous souhaiterez parfois connaître l'état d'un composant différent depuis un composant particulier, plus souvent dans les cas d'utilisation liés à la validation dépendante de l'action/la valeur. Pour cela, l'attribut binding
peut être utilisé, mais pas en combinaison avec une propriété de bean. Vous pouvez simplement spécifier un nom de variable unique dans l'étendue EL locale dans l'attribut binding
comme so binding="#{foo}"
et le composant est pendant la réponse au rendu ailleurs dans la même vue directement en tant que UIComponent
référence disponible par #{foo}
. Voici plusieurs questions connexes pour lesquelles une telle solution a été utilisée dans la réponse:
tilisez une expression EL pour transmettre un ID de composant à un composant composite dans JSF
(et cela ne concerne que le mois dernier ...)
chaque composant JSF se transforme en HTML et contrôle totalement le code HTML qu'il produit. JSF peut utiliser de nombreuses astuces, et l’une de ces astuces à utiliser dépend de l’implémentation de JSF que vous utilisez.
Pour des choses comme hlink, vous pouvez inclure des informations de liaison dans l'URL en tant que paramètres de requête ou en tant que partie de l'URL elle-même ou en tant que paramètres matrx. pour des exemples.
http:..../somelink?componentId=123
permettrait à jsf de regarder dans l’arborescence des composants pour voir que le lien 123 a été cliqué. ou il pourrait e htp:..../jsf;LinkId=123
Le moyen le plus simple de répondre à cette question consiste à créer une page JSF avec un seul lien, puis à examiner le résultat HTML généré. De cette façon, vous saurez exactement comment cela se passe avec la version de JSF que vous utilisez.