Wie funktioniert es?
Wenn eine JSF-Ansicht (Facelets / JSP-Datei) erstellt / wiederhergestellt wird, wird ein JSF-Komponentenbaum erstellt. In diesem Moment, der Erstellungszeit der Ansicht , werden alle binding
Attribute ausgewertet ( zusammen mit id
Attributen und Taghandlern wie JSTL ). Wenn die JSF-Komponente erstellt werden muss, bevor sie zum Komponentenbaum hinzugefügt wird, prüft JSF, ob das binding
Attribut eine vorgefertigte Komponente (dh keine) zurückgibt null
, und verwendet sie dann , wenn dies der Fall ist. Wenn es nicht vorgefertigt ist, erstellt JSF die Komponente automatisch "auf die übliche Weise" und ruft den dahinter liegenden Setter aufbinding
Attribut mit der automatisch erstellten Komponenteninstanz als Argument auf.
In Effekten bindet es eine Referenz der Komponenteninstanz im Komponentenbaum an eine Variable mit Gültigkeitsbereich. Diese Informationen sind in der generierten HTML-Darstellung der Komponente selbst in keiner Weise sichtbar. Diese Informationen sind für die generierte HTML-Ausgabe ohnehin keineswegs relevant. Wenn das Formular gesendet und die Ansicht wiederhergestellt wird, wird der JSF-Komponentenbaum einfach von Grund auf neu erstelltbinding
Attribute werden wie im obigen Absatz beschrieben neu bewertet. Nachdem der Komponentenbaum neu erstellt wurde, stellt JSF den JSF-Ansichtsstatus im Komponentenbaum wieder her.
Komponenteninstanzen haben einen Anforderungsbereich!
Es ist wichtig zu wissen und zu verstehen, dass die konkreten Komponenteninstanzen einen effektiven Anforderungsbereich haben. Sie werden bei jeder Anforderung neu erstellt und ihre Eigenschaften werden während der Wiederherstellungsansichtsphase mit Werten aus dem JSF-Ansichtsstatus gefüllt. Wenn Sie die Komponente an eine Eigenschaft einer Backing-Bean binden, sollte sich die Backing-Bean auf keinen Fall in einem breiteren Bereich als dem Anforderungsbereich befinden. Siehe auch JSF 2.0-Spezifikation Kapitel 3.1.5:
3.1.5 Komponentenbindungen
...
Komponentenbindungen werden häufig in Verbindung mit JavaBeans verwendet, die dynamisch über die Funktion zum Erstellen verwalteter Beans instanziiert werden (siehe Abschnitt 5.8.1 „VariableResolver und der StandardvariableResolver“). Es wird dringend empfohlen, dass Anwendungsentwickler verwaltete Beans, auf die durch Komponentenbindungsausdrücke verwiesen wird, im Bereich "Anfrage" platzieren. Dies liegt daran, dass das Platzieren im Sitzungs- oder Anwendungsbereich Thread-Sicherheit erfordern würde, da UIComponent-Instanzen davon abhängen, ob sie in einem einzelnen Thread ausgeführt werden. Es gibt auch potenziell negative Auswirkungen auf die Speicherverwaltung, wenn eine Komponentenbindung in den Sitzungsbereich gestellt wird.
Andernfalls werden Komponenteninstanzen von mehreren Anforderungen gemeinsam genutzt, was möglicherweise zu einer " doppelten Komponenten-ID" führt Fehlern " und "seltsamen" Verhaltensweisen führt, da in der Ansicht deklarierte Validatoren, Konverter und Listener aus früheren Anforderungen erneut an die vorhandene Komponenteninstanz angehängt werden. Die Symptome sind klar: Sie werden mehrmals ausgeführt, einmal mehr bei jeder Anforderung im selben Bereich, an den die Komponente gebunden ist.
Und unter hoher Last (dh wenn mehrere verschiedene HTTP-Anforderungen (Threads) gleichzeitig auf dieselbe Komponenteninstanz zugreifen und diese bearbeiten ) kann es früher oder später zu einem Anwendungsabsturz kommen, z. B. mit festgefahrenem Thread bei UIComponent.popComponentFromEL oder Java-Threads bei 100% CPU-Auslastung unter Verwendung von Richfaces UIDataAdaptorBase und seiner internen HashMap oder sogar etwas "seltsam" IndexOutOfBoundsException
oder ConcurrentModificationException
direkt aus dem Quellcode der JSF-Implementierung stammend, während JSF damit beschäftigt ist, den Ansichtsstatus zu speichern oder wiederherzustellen (dh der Stack-Trace zeigt saveState()
oder restoreState()
Methoden und ähnliches an).
Die Verwendung binding
auf einer Bean-Eigenschaft ist eine schlechte Praxis
Unabhängig binding
davon ist das Binden einer gesamten Komponenteninstanz an eine Bean-Eigenschaft auf diese Weise, selbst bei einer Bean mit Anforderungsbereich, in JSF 2.x ein eher seltener Anwendungsfall und im Allgemeinen nicht die beste Vorgehensweise. Es zeigt einen Designgeruch an. Sie erklären normalerweise Komponenten in der Ansicht Seite und bindet ihre Laufzeit Attribute wie value
, und vielleicht auch andere mögen styleClass
, disabled
, rendered
, usw, in den normalen Bean - Eigenschaften. Anschließend bearbeiten Sie einfach genau die gewünschte Bean-Eigenschaft, anstatt die gesamte Komponente zu erfassen und die dem Attribut zugeordnete Setter-Methode aufzurufen.
In den Fällen , wenn eine Komponente needs „dynamisch aufgebaut“ werden basierend auf einem statischen Modell ist besser zu nutzen Ansicht Kompilierzeit Tags wie JSTL , falls erforderlich in einer Tag - Datei , statt createComponent()
, new SomeComponent()
, getChildren().add()
und was nicht. Siehe auch Wie kann ein Snippet einer alten JSP in ein JSF-Äquivalent umgestaltet werden?
Oder, wenn eine Komponente Bedürfnisse auf einem dynamischen Modell basierend „dynamisch wiedergegeben“ werden, dann benutzen Sie einfach eine Iterator Komponente ( <ui:repeat>
, <h:dataTable>
usw.). Siehe auch So fügen Sie JSF-Komponenten dynamisch hinzu .
Composite-Komponenten sind eine ganz andere Geschichte. Es ist völlig legitim, Komponenten innerhalb von a <cc:implementation>
an die Hintergrundkomponente zu binden (dh die durch gekennzeichnete Komponente <cc:interface componentType>
. Siehe auch ao java.util.Date über zwei h teilen: inputText-Felder, die Stunde und Minute mit f: convertDateTime darstellen, und wie eine dynamische Liste mit implementiert wird eine JSF 2.0-Verbundkomponente?
Nur binding
im lokalen Bereich verwenden
Manchmal möchten Sie jedoch mehr über den Status einer anderen Komponente innerhalb einer bestimmten Komponente erfahren, mehr als häufig in Anwendungsfällen im Zusammenhang mit der aktions- / wertabhängigen Validierung. Dafür kann das binding
Attribut verwendet werden, jedoch nicht in Kombination mit einer Bean-Eigenschaft. Sie können im binding
Attribut einfach einen eindeutigen Variablennamen im lokalen EL-Bereich angeben , binding="#{foo}"
und die Komponente befindet sich während der Renderantwort an einer anderen Stelle in derselben Ansicht direkt als UIComponent
Referenz, die von verfügbar ist #{foo}
. Hier sind einige verwandte Fragen, bei denen eine solche Lösung in der Antwort verwendet wurde:
Siehe auch:
User.User(), User.getLink(), User.setLink(), User.getValue()
Wenn ich auf den LinkUser.User(), User.setLink()...
UIViewRoot
(alles imUIComponent
Grunde) ist sowieso unserialisierbar.Jede JSF-Komponente rendert sich selbst in HTML und hat die vollständige Kontrolle darüber, welches HTML sie erzeugt. Es gibt viele Tricks, die von JSF verwendet werden können, und genau, welche dieser Tricks verwendet werden, hängt von der von Ihnen verwendeten JSF-Implementierung ab.
Für Dinge wie hlink können Sie Bindungsinformationen als Abfrageparameter oder als Teil der URL selbst oder als matrx-Parameter in die URL aufnehmen. zum Beispiel.
http:..../somelink?componentId=123
würde jsf erlauben, in den Komponentenbaum zu schauen, um zu sehen, dass auf Link 123 geklickt wurde. oder es könnte ehtp:..../jsf;LinkId=123
Die einfachste Möglichkeit, diese Frage zu beantworten, besteht darin, eine JSF-Seite mit nur einem Link zu erstellen und anschließend die von ihr erzeugte HTML-Ausgabe zu untersuchen. Auf diese Weise wissen Sie genau, wie dies mit der von Ihnen verwendeten JSF-Version geschieht.
quelle
action
und festgelegt habevalue
und dann das JSF-Framework seinen Job machen ließ.user
als verwaltete Bean mit Anwendungsbereich gespeichert, und wenn ich jedes Mal auf den Link klicke,value="-908991273579182886:-7278326187282654551"
ändert sich nur die zweite Zahl , und alles andere ist gleich. Ich frage mich, was diese Magie bewirkt.