Comment l'attribut "liant" fonctionne-t-il dans le JSF? Quand et comment doit-il être utilisé?

il y a beaucoup de matériaux qui différencient l'attribut value et l'attribut binding dans JSF.

Je m'intéresse à la différence entre les deux approches. Donnée:

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 retourner la valeur de propriété name du haricot User . La valeur est imprimée en sortie HTML.

mais je ne comprenais pas comment binding fonctionnait. Comment le HTML généré maintient-il une liaison avec la propriété link de la fève User ?

ci-dessous est la partie pertinente de la sortie générée après embellissement manuel et commentaire (notez que l'id j_id_jsp_1847466274_1 a été généré automatiquement et qu'il y a deux widgets d'entrée cachés). J'utilise le 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ù est le binding stocké ici?

66
demandé sur BalusC 2013-02-16 18:09:17

2 réponses

comment ça marche?

Lorsqu'une vue JSF (Facelets/JSP file) est construite/restaurée, un arbre de composants JSF sera produit. À ce moment, le view build time , tous les attributs binding sont évalués ( avec id attributs et taghandlers comme JSTL ). Lorsque le composant JSF doit être créé avant d'être ajouté à l'arbre des composants, JSF vérifiera si l'attribut binding renvoie un composant pré-créé (c. - à-d. non - null ) et si oui, l'utiliser. Si elle n'est pas pré-créée, alors JSF va autocréer le composant "de la manière habituelle" et invoquer le setter derrière l'attribut binding avec l'instance du composant autocréée comme argument.

dans les effets, il lie une référence de l'instance composant dans l'arbre composant à une variable scopée. Cette information n'est en aucun cas visible dans la représentation HTML générée du composant lui-même. Ce les informations ne sont en aucun cas pertinentes pour la sortie HTML générée de toute façon. Lorsque le formulaire est soumis et que la vue est restaurée, l'arbre des composants JSF est simplement reconstruit à 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'arbre des composants recréé, JSF restaurera l'état de vue JSF dans l'arbre des composants.

Les instances de composants

sont des requêtes scoped!

Important à savoir et comprendre est que les instances de composants concrets sont effectivement demande scoped. Ils sont nouvellement créés sur chaque requête et leurs propriétés sont remplies de valeurs de l'état de vue JSF pendant la phase de restauration. Ainsi, si vous liez le composant à une propriété d'un haricot de soutien, alors le haricot de soutien devrait absolument pas être dans une portée plus large que la portée de la requête. Voir aussi JSF 2.0 specification chapitre 3.1.5:

3.1.5 Fixations Des Composants

...

les fixations de composants sont souvent utilisées en conjonction avec des JavaBeans qui sont instanciés dynamiquement via le Managed Bean Creation facility (voir Section 5.8.1 "VariableResolver and the Default VariableResolver"). il est fortement recommander aux développeurs d'applications de placer des fèves gérées qui sont pointées par des expressions de liaison de composants dans "la demande" de la portée. en effet, sa mise en session ou son champ d'application nécessiterait la sécurité des fils, puisque Les instances UIComponent dépendent de l'exécution à l'intérieur d'un seul thread. Il y a aussi des impacts potentiellement négatifs sur gestion de la mémoire lors de la mise en place de la reliure d'un composant dans le champ d'application "session".

sinon, les instances de composants sont partagées entre plusieurs requêtes, ce qui peut entraîner " duplicate component ID " des erreurs et les comportements "bizarres" parce que les validateurs, les convertisseurs et les écouteurs déclarés dans la vue sont re-attachés à l'instance du composant existant à partir de la(Des) requête (s) précédente (s). Les symptômes sont clairs: ils sont exécutés plusieurs fois, une fois de plus avec chaque requête dans la même portée que le composant est lié.

et, en cas de charge importante (c'est-à-dire lorsque plusieurs requêtes HTTP (threads) différentes accèdent et manipulent la même instance de Composant en même temps), vous pouvez faire face tôt ou tard à un crash d'application avec par exemple fil collé à UIComponent.popComponentFromEL , ou fils Java à 100% D'utilisation CPU en utilisant richfaces UIDataAdaptorBase et son HashMap interne , ou même certains" étrange IndexOutOfBoundsException ou ConcurrentModificationException venant directement du code source de mise en œuvre JSF pendant que JSF est occupé à sauvegarder ou restaurer l'état de la vue (i.e. la trace de la pile indique saveState() ou restoreState() méthodes et similaires).

utiliser binding sur une propriété de haricot est une mauvaise pratique

indépendamment, en utilisant binding de cette façon, lier une instance de Composant entière à une propriété de haricot, même sur une demande scoped bean, est dans JSF 2.x un cas d'utilisation assez rare et généralement pas la meilleure pratique. Ça indique une odeur de design. Normalement, vous déclarez les composants du côté vue et liez leurs attributs runtime comme value , et peut-être d'autres comme styleClass , disabled , rendered , etc., aux propriétés normales des haricots. Ensuite, vous manipulez exactement la propriété bean que vous voulez au lieu de saisir l'ensemble du composant et d'appeler la méthode setter associée à l'attribut.

dans les cas où un composant doit être "construit dynamiquement" basé sur un modèle statique, mieux est d'utiliser voir construire des étiquettes de temps comme JSTL , si nécessaire dans un tag file , au lieu de createComponent() , new SomeComponent() , getChildren().add() et ce qui ne l'est pas. Voir aussi

ou, si un composant doit être "rendu dynamiquement" sur la base d'un modèle dynamique, utilisez simplement un itérateur ( <ui:repeat> , <h:dataTable> , etc). Voir aussi comment ajouter dynamiquement les composants JSF .

les composants composites sont entièrement autre histoire. Il est tout à fait légitime de lier des composants à l'intérieur d'un <cc:implementation> au composant de support (c.-à-d. le composant identifié par <cc:interface componentType> ). Voir aussi a. O. Split java.util.Date de plus de deux h:inputText champs représentant les heures et les minutes avec f:convertDateTime et Comment mettre en place une liste dynamique avec JSF 2.0 Composite Composant?

utiliser uniquement binding dans le champ d'application local

Cependant, vous aimeriez parfois connaître l'état d'un composant différent à l'intérieur d'un composant particulier, plus que souvent dans les cas d'utilisation liés à la validation dépendante action/valeur. Pour cela, l'attribut binding peut être utilisé, mais pas en combinaison avec une propriété bean. Vous pouvez simplement spécifier un nom de variable unique dans la portée EL locale dans l'attribut binding comme so binding="#{foo}" et le composant est en cours de réponse de rendu ailleurs dans le même vue directement que UIComponent référence disponible par #{foo} . Voici plusieurs questions connexes où une telle solution est utilisée dans la réponse:

Voir aussi:

109
répondu BalusC 2017-05-23 11:47:26

chaque composant JSF se rend en HTML et a le contrôle complet de ce QU'il produit en HTML. Il y a de nombreux trucs qui peuvent être utilisés par JSF, et exactement lequel de ces trucs sera utilisé dépend de la mise en œuvre JSF que vous utilisez.

  • S'assurer que chaque de l'entrée a un nom unique total, de sorte que lorsque le formulaire est soumis de nouveau à l'arbre des composants qui l'a rendu, il est facile de dire où chaque composant peut lire sa forme de valeur.
  • le composant JSF peut générer javascript qui renvoie au serer, le javascript généré sait où chaque composant est lié aussi, car il a été généré par le composant.
  • pour des choses comme hlink vous pouvez inclure des informations de liaison dans l'url comme paramètres de requête ou comme partie de l'url elle-même ou comme paramètres matrx. exemple.

    http:..../somelink?componentId=123 permettrait à jsf de regarder dans l'arbre des composants pour voir ce lien 123 a été cliqué. ou il pourrait e htp:..../jsf;LinkId=123

la meilleure façon de répondre à cette question Est de créer une page JSF avec un seul lien, puis d'examiner la sortie html qu'elle produit. De cette façon, vous saurez exactement comment cela se produit en utilisant la version de JSF que vous utilisez.

0
répondu ams 2013-02-16 15:50:12