Wann sollten <ui: include>, Tag-Dateien, zusammengesetzte Komponenten und / oder benutzerdefinierte Komponenten verwendet werden?

102

Ich habe kürzlich angefangen, JSF 2.0 mit Facelets zu verwenden, und war verwirrt über neue Verbundkomponenten, die die vorhandenen <ui:include>und anderen von Facelets 1.x angebotenen Template-Techniken kennen.

Was ist der Unterschied zwischen diesen Ansätzen? Funktionell scheinen sie ungefähr dasselbe zu bieten: <ui:param>vs <cc:attribute>, <ui:insert>+ <ui:define>vs Tag-Dateien, Wiederverwendung der vorhandenen Vorlagen. Gibt es bei Verbundkomponenten noch etwas anderes als Syntax und klare Schnittstellenspezifikation? Könnte sich die Leistung unterscheiden?

mrembisz
quelle

Antworten:

176

Was ist der Unterschied zwischen diesen Ansätzen?

Facelet-Vorlagen

Verwenden Facelet Vorlagen (wie in <ui:composition>, <ui:include>und <ui:decorate>) , wenn Sie Haupt-Seitenlayout - Fragmente in wiederverwendbare Vorlagen spalten. ZB Kopfzeile, Menü, Inhalt, Fußzeile usw.

Beispiele:

Facelet-Tag-Dateien

Verwenden Sie Facelet-Tag-Dateien, wenn Sie eine wiederverwendbare Gruppe von Komponenten haben möchten, um Codeduplikationen zu verhindern / zu minimieren. ZB eine Gruppe von Label + Input + Message-Komponenten. Der Hauptunterschied zu zusammengesetzten Komponenten besteht darin, dass die Ausgabe einer Facelet-Tag-Datei keine einzelne darstellt UIComponentund unter bestimmten Umständen die einzige Lösung darstellt, wenn eine zusammengesetzte Komponente nicht ausreicht. Im Allgemeinen ist eine <ui:include>mit einer oder mehreren, <ui:param>die eine verwaltete Bean-Eigenschaft (und damit kein fest codierter Wert) übergibt, ein Signal dafür, dass die Include-Datei besser eine Tag-Datei sein kann.

Beispiele:

Verbundbauteile

Verwenden Sie zusammengesetzte Komponenten, wenn Sie eine einzelne und wiederverwendbare benutzerdefinierte Komponente UIComponentmit einer einzigen Verantwortung unter Verwendung von reinem XML erstellen möchten . Eine solche zusammengesetzte Komponente besteht normalerweise aus einer Reihe vorhandener Komponenten und / oder HTML und wird physisch als einzelne Komponente gerendert und soll an eine einzelne Bean-Eigenschaft gebunden sein. ZB eine Komponente, die eine einzelne java.util.DateEigenschaft durch 3 abhängige <h:selectOneMenu>Komponenten darstellt, oder eine Komponente, die eine einzelne benutzerdefinierte Entität als Eigenschaft kombiniert <p:fileUpload>und <p:imageCropper>zu einer einzelnen <my:uploadAndCropImage>verweist com.example.Image.

Beispiele:

Benutzerdefinierte Komponenten

Verwenden Sie eine benutzerdefinierte Komponente, wenn die Funktionalität mit Facelet-Tag-Dateien oder zusammengesetzten Komponenten nicht erreicht werden kann, da der Standard- / verfügbare Komponentensatz keine Unterstützung bietet. Beispiele finden sich überall im Quellcode von Open-Source-Komponentenbibliotheken wie PrimeFaces und OmniFaces .

Tag-Handler

Wenn Sie die Erstellung des JSF-Komponentenbaums steuern möchten, anstatt die HTML-Ausgabe zu rendern, sollten Sie anstelle einer Komponente einen Tag-Handler verwenden.

Beispiele:

Beispielprojekte

Hier sind einige Beispielprojekte, die alle oben genannten Techniken verwenden.


Könnte sich die Leistung unterscheiden?

Technisch gesehen ist das Leistungsproblem vernachlässigbar. Die Auswahl sollte auf der Grundlage der konkreten funktionalen Anforderungen und des endgültigen Abstraktionsgrades, der Wiederverwendbarkeit und der Wartbarkeit der Implementierung erfolgen. Jeder Ansatz hat seinen eigenen, genau definierten Zweck und seine eigenen Grenzen.

Zusammengesetzte Komponenten haben jedoch einen erheblichen Overhead beim Erstellen / Wiederherstellen der Ansicht (insbesondere: beim Speichern / Wiederherstellen des Ansichtsstatus). In älteren Versionen von Mojarra hatten Verbundkomponenten Leistungsprobleme beim Zuweisen von Standardwerten. Dies ist bereits seit 2.1.13 behoben. Außerdem hatte Mojarra einen Speicherverlust, wenn a <cc:attribute method-signature>für Methodenausdrücke verwendet wird. Im Grunde wird der gesamte Komponentenbaum in einer HTTP-Sitzung erneut referenziert. Dies ist seit 2.1.29 / 2.2.8 behoben. Der Speicherverlust kann in älteren 2.1-Versionen wie folgt umgangen werden:

<context-param>
    <param-name>com.sun.faces.serializeServerState</param-name>
    <param-value>true</param-value>
</context-param>

Oder in älteren 2.2-Versionen wie folgt:

<context-param>
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name>
    <param-value>true</param-value>
</context-param>

Wenn Sie jedoch relativ "viele" Verbundkomponenten haben und sich darauf javax.faces.STATE_SAVING_METHODeingestellt haben client, wird die Leistung schmerzhaft sein. Missbrauchen Sie keine zusammengesetzten Komponenten, wenn Sie lediglich die Grundfunktionalität wünschen, die bereits mit einer einfachen Include- oder Tag-Datei möglich ist. Verwenden Sie die einfache Konfiguration (lesen Sie: keine *.taglib.xmlDatei erforderlich) nicht als Ausrede, um zusammengesetzte Komponenten Tag-Dateien vorzuziehen.

Vergessen Sie bei Verwendung von Mojarra 2.2.10 oder älter nicht, die relativ kurze Aktualisierungszeit von Facelets für den Produktionsmodus zu deaktivieren:

<context-param>
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name>
    <param-value>-1</param-value>
</context-param>

Verwenden Sie diese Einstellung nicht für die Entwicklung, da Sie sonst den gesamten Server neu starten müssen, damit Änderungen in den Facelets-Dateien übernommen werden! Mojarra 2.2.11 und neuer, und MyFaces ist bereits standardmäßig auf -1wann javax.faces.PROJECT_STAGEnicht eingestellt Development.

BalusC
quelle
Warum sollten Sie 1 Komponente (zusammengesetzte Komponente) anstelle von 3 (Facelet-Tag-Datei) rendern? Ich meine, an einem sonnigen Tag fühlen Sie sich vielleicht wie 1 statt 3 ... aber ich denke, dahinter steckt noch etwas anderes. In Ihrem Beispiel erweitern Sie UINamingContainer ... könnte dies einer der Gründe sein, sich für ein CC zu entscheiden (um einige jsf-implementierungsspezifische Funktionen überschreiben zu können)?
Toskan
2
Eine Tag-Datei sollte als eine Art Include angesehen werden. Eine zusammengesetzte Komponente sollte als echte Komponente betrachtet werden. Eine zusammengesetzte Komponente muss implementiert NamingContainerwerden. Andernfalls treten Probleme mit doppelten IDs auf, wenn dieselbe Komponente mehrmals wiederverwendet wird.
BalusC
@BalusC Angenommen, ich habe eine Reihe von HTML- und JSF-Dateien, die einen Block erstellen, mit dem ich Adressen (und alle Attribute: Straße, Nummer, Stadt usw.) hinzufügen oder entfernen kann. Ich muss denselben Block auf 2 oder 3 Seiten verwenden. Fällt das unter Ihre Beschreibung einer zusammengesetzten Komponente?
RinaldoPJr
1
@Rinaldo: Ich denke, ich würde dafür eine Tag-Datei mit dynamisch aufgefüllten Komponenten-IDs verwenden, wie in stackoverflow.com/questions/5713718/… gezeigt. . IMO, wenn es mit einer Tag-Datei möglich ist, verwenden Sie es. Wenn dies mit einer Tag-Datei nicht möglich ist, verwenden Sie einen Verbund. Wenn Sie mehrere Komponenten benötigen, um eine einzelne Eigenschaft zu bearbeiten (keine Adresse, sondern z. B. Straßenname + Hausnummer, die in einer einzelnen Eigenschaft enthalten sein sollte), ist eine zusammengesetzte Komponente die einzige Lösung.
BalusC
2
@Tarik: Composites haben im Vergleich zu Tagfiles viel Overhead. Mit anderen Worten: schlechte Leistung. Verwenden Sie diese Option nur, wenn Sie eine einzelne benutzerdefinierte UI-Komponente basierend auf einer Reihe eng verwandter vorhandener Komponenten erstellen müssen. Dies ist mit einer Tag-Datei nicht möglich. ZEEF.com hat zum Beispiel nur einen Verbund: das All-in-One-Bild zum Hochladen / Herunterladen / Zuschneiden, das unter anderem für Seitenbilder, Profilbilder, Linkblock-Header, Bildblöcke usw. verwendet wird. Es ist nur an eine ImageEigenschaft gebunden in Bohne.
BalusC