Wofür ist die JSF-Ressourcenbibliothek gedacht und wie sollte sie verwendet werden?

228

Die JSF <h:outputStylesheet>, <h:outputScript>und <h:graphicImage>Komponenten haben ein libraryAttribut. Was ist das und wie soll das verwendet werden? Es gibt viele Beispiele auf dem Netz , die sie verwenden , wie mit dem gemeinsamen Inhalt / Dateityp folgen css, jsund img(oder image) als Bibliotheksnamen auf dem Tag je verwendet:

<h:outputStylesheet library="css" name="style.css" />
<h:outputScript library="js" name="script.js" />
<h:graphicImage library="img" name="logo.png" />

Wie ist es nützlich? Der libraryWert in diesen Beispielen scheint nur das zu wiederholen, was bereits durch den Tag-Namen dargestellt wurde. Für a <h:outputStylesheet>basiert es auf dem Tag-Namen, der bereits offensichtlich ist, dass es eine "CSS-Bibliothek" darstellt. Was ist der Unterschied zu Folgendem, das genauso funktioniert?

<h:outputStylesheet name="css/style.css" />
<h:outputScript name="js/script.js" />
<h:graphicImage name="img/logo.png" />

Auch die generierte HTML-Ausgabe ist etwas anders. Bei einem gegebenen Kontextpfad /contextnameund einer FacesServletZuordnung zu einem URL-Muster von *.xhtmlgeneriert der erstere den folgenden HTML-Code mit dem Bibliotheksnamen als Anforderungsparameter:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/style.css.xhtml?ln=css" />
<script type="text/javascript" src="/contextname/javax.faces.resource/script.js.xhtml?ln=js"></script>
<img src="/contextname/javax.faces.resource/logo.png.xhtml?ln=img" alt="" />

Während letzterer den folgenden HTML-Code mit dem Bibliotheksnamen nur im Pfad des URI generiert:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml" alt="" />

Der letztere Ansatz ist im Nachhinein auch sinnvoller als der erstere. Wie genau ist das libraryAttribut dann nützlich?

BalusC
quelle

Antworten:

256

Tatsächlich sind alle Beispiele im Web, bei denen der allgemeine Inhalt / Dateityp wie "js", "css", "img" usw. als Bibliotheksname verwendet wird, irreführend .

Beispiele aus der Praxis

Schauen wir uns zunächst an, wie vorhandene JSF-Implementierungen wie Mojarra und MyFaces sowie JSF-Komponentenbibliotheken wie PrimeFaces und OmniFaces diese verwenden. Keiner von ihnen verwendet Ressourcenbibliotheken auf diese Weise. Sie verwenden es (unter der Decke, von @ResourceDependencyoder UIViewRoot#addComponentResource()) wie folgt:

<h:outputScript library="javax.faces" name="jsf.js" />
<h:outputScript library="primefaces" name="jquery/jquery.js" />
<h:outputScript library="omnifaces" name="omnifaces.js" />
<h:outputScript library="omnifaces" name="fixviewstate.js" />
<h:outputScript library="omnifaces.combined" name="[dynamicname].js" />
<h:outputStylesheet library="primefaces" name="primefaces.css" />
<h:outputStylesheet library="primefaces-aristo" name="theme.css" />
<h:outputStylesheet library="primefaces-vader" name="theme.css" />

Es sollte klar werden, dass es sich im Wesentlichen um den allgemeinen Namen der Bibliothek / des Moduls / des Themas handelt dem alle diese Ressourcen gehören.

Einfachere Identifizierung

Auf diese Weise ist es viel einfacher anzugeben und zu unterscheiden, woher diese Ressourcen gehören und / oder woher sie stammen. Stellen Sie sich vor, Sie haben zufällig eine primefaces.cssRessource in Ihrer eigenen Webanwendung, in der Sie einige Standard-CSS von PrimeFaces überschreiben / optimieren. wenn PrimeFaces keinen eigenen Bibliotheksnamen verwendet hatprimefaces.css würde, würde der eigene PrimeFaces- nicht geladen, sondern der von der Webanwendung bereitgestellte, der das Erscheinungsbild beeinträchtigen würde.

Wenn Sie eine benutzerdefinierte Funktion verwenden ResourceHandler, können Sie auch die Ressourcen aus einer bestimmten Bibliothek genauer steuern , wenn sie ordnungsgemäß libraryverwendet werden. Wenn alle Komponentenbibliotheken "js" für alle ihre JS-Dateien verwendet hätten, wie würde das ResourceHandlerjemals unterscheiden, wenn es von einer bestimmten Komponentenbibliothek stammt? Beispiele sind OmniFaces CombinedResourceHandlerund GraphicResourceHandler; Überprüfen Sie die createResource()Methode, bei der die Bibliothek überprüft wird, bevor Sie sie an den nächsten Ressourcenhandler in der Kette delegieren. Auf diese Weise wissen sie, wann CombinedResourceoder zu welchem GraphicResourceZweck sie erstellen müssen .

Es sollte beachtet werden, dass RichFaces es falsch gemacht hat. Es wurden überhaupt keine verwendet libraryund eine weitere Ebene für die Ressourcenverarbeitung wurde selbst erstellt. Daher ist es unmöglich, RichFaces-Ressourcen programmgesteuert zu identifizieren. Genau aus diesem Grund musste OmniFaces einen reflexionsbasierten HackCombinedResourceHander einführen , damit er trotzdem mit RichFaces-Ressourcen funktioniert.

Deine eigene Webanwendung

Ihre eigene Webanwendung benötigt nicht unbedingt eine Ressourcenbibliothek. Am besten lassen Sie es einfach weg.

<h:outputStylesheet name="css/style.css" />
<h:outputScript name="js/script.js" />
<h:graphicImage name="img/logo.png" />

Wenn Sie wirklich einen benötigen, können Sie ihm auch einen vernünftigeren gebräuchlichen Namen geben, z. B. "Standard" oder einen Firmennamen.

<h:outputStylesheet library="default" name="css/style.css" />
<h:outputScript library="default" name="js/script.js" />
<h:graphicImage library="default" name="img/logo.png" />

Wenn die Ressourcen für eine Master-Facelets-Vorlage spezifisch sind, können Sie ihr auch den Namen der Vorlage geben, damit sie leichter miteinander in Beziehung gesetzt werden können. Mit anderen Worten, es dient eher der Selbstdokumentation. ZB in einer /WEB-INF/templates/layout.xhtmlVorlagendatei:

<h:outputStylesheet library="layout" name="css/style.css" />
<h:outputScript library="layout" name="js/script.js" />

Und eine /WEB-INF/templates/admin.xhtmlVorlagendatei:

<h:outputStylesheet library="admin" name="css/style.css" />
<h:outputScript library="admin" name="js/script.js" />

Ein Beispiel aus der Praxis finden Sie im OmniFaces-Showcase-Quellcode .

Wenn Sie dieselben Ressourcen über mehrere Webanwendungen gemeinsam nutzen möchten und ein "gemeinsames" Projekt dafür erstellt haben, das auf demselben Beispiel wie in dieser Antwort basiert und wiederum als JAR in Webanwendungen eingebettet ist /WEB-INF/lib, verweisen Sie es auch als Bibliothek (Der Name steht Ihrer Wahl frei; Komponentenbibliotheken wie OmniFaces und PrimeFaces funktionieren ebenfalls so):

<h:outputStylesheet library="common" name="css/style.css" />
<h:outputScript library="common" name="js/script.js" />
<h:graphicImage library="common" name="img/logo.png" />

Versionierung der Bibliothek

Ein weiterer Hauptvorteil besteht darin, dass Sie die Versionierung der Ressourcenbibliothek auf die von Ihrer eigenen Webanwendung bereitgestellten Ressourcen richtig anwenden können (dies funktioniert nicht für in eine JAR eingebettete Ressourcen). Sie können im Bibliotheksordner einen direkten untergeordneten Unterordner mit einem Namen im \d+(_\d+)*Muster erstellen , um die Version der Ressourcenbibliothek anzugeben.

WebContent
 |-- resources
 |    `-- default
 |         `-- 1_0
 |              |-- css
 |              |    `-- style.css
 |              |-- img
 |              |    `-- logo.png
 |              `-- js
 |                   `-- script.js
 :

Bei Verwendung dieses Markups:

<h:outputStylesheet library="default" name="css/style.css" />
<h:outputScript library="default" name="js/script.js" />
<h:graphicImage library="default" name="img/logo.png" />

Dadurch wird der folgende HTML-Code mit der Bibliotheksversion als vParameter generiert :

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml?ln=default&amp;v=1_0" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&amp;v=1_0"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&amp;v=1_0" alt="" />

Wenn Sie also eine Ressource bearbeitet / aktualisiert haben, müssen Sie lediglich den Versionsordner kopieren oder in einen neuen Wert umbenennen. Wenn Sie mehrere Versionsordner haben, stellt die JSF ResourceHandlerdie Ressource automatisch ab der höchsten Versionsnummer gemäß den Regeln für die numerische Reihenfolge bereit.

Wenn Sie also einen resources/default/1_0/*Ordner resources/default/1_1/*wie folgt kopieren / umbenennen :

WebContent
 |-- resources
 |    `-- default
 |         |-- 1_0
 |         |    :
 |         |
 |         `-- 1_1
 |              |-- css
 |              |    `-- style.css
 |              |-- img
 |              |    `-- logo.png
 |              `-- js
 |                   `-- script.js
 :

Dann würde das letzte Markup-Beispiel den folgenden HTML-Code generieren:

<link rel="stylesheet" type="text/css" href="/contextname/javax.faces.resource/css/style.css.xhtml?ln=default&amp;v=1_1" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&amp;v=1_1"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&amp;v=1_1" alt="" />

Dadurch wird der Webbrowser gezwungen, die Ressource direkt vom Server anzufordern, anstatt die gleichnamige Ressource aus dem Cache anzuzeigen, wenn die URL mit dem geänderten Parameter zum ersten Mal angefordert wird. Auf diese Weise müssen die Endbenutzer keine feste Aktualisierung durchführen (Strg + F5 usw.), wenn sie die aktualisierte CSS / JS-Ressource abrufen müssen.

Bitte beachten Sie, dass die Bibliotheksversionierung für Ressourcen, die in einer JAR-Datei enthalten sind, nicht möglich ist. Du würdest einen Brauch brauchen ResourceHandler. Siehe auch Verwenden der JSF-Versionierung für Ressourcen in jar .

Siehe auch:

BalusC
quelle
2
Ist es möglich, EL für die Bibliothek zu verwenden? Wenn ich also Ressourcen / Standard und Ressourcen / FeelingFroggyToday haben wollte, könnte ich so etwas wie library = "# {someLibraryHere}" tun, um someLibraryHere meiner ausgewählten Bibliothek zuzuordnen, und mich nicht jedes Mal darauf verlassen müssen, das Ressourcenverzeichnis in eine höhere Version umzubenennen Ich wollte sie ändern.
Gebuh
Wenn Sie library = admin oder libray = layout sagen, befinden sich diese Ordner (admin und layout) im Ressourcenordner?
Koray Tugay
Umm. Sehr interessanter Balus. Ich habe ein Problem in einer Web-App, bei der die Datei theme.css beim Laden leer erscheint. Dies geschieht erst nach verschiedenen Neueinsätzen (in JBOSS EAP). Die CSS-URL lautet wie folgt: /javax.faces.resource/css/theme.css.xhtml?ln=default&v=3_3_0_130416 und wird folgendermaßen deklariert: <h: outputStylesheet library = "default" name = "css / theme. css "target =" head "/>. Möglicherweise hängt dieses Problem mit Versionsproblemen zusammen?
Ricardo Vila
2
Haben sich die zulässigen Zeichen für den Wert von libraryoder etwas damit verbundenes zwischen mojarra 2.2.5 (2.2.5-jbossorg-3, wildfly 8.0) und 2.2.11 (2.2.11-jbossorg-1) geändert? Ich kann anscheinend nichts in den Veröffentlichungen finden. Siehe stackoverflow.com/questions/35719808/…
Kukeltje
3
Danke @BalusC. Leider gibt sogar das Java EE 7-Lernprogramm von Oracle das falsche Beispiel an, indem ein Bibliotheksname cssin Kapitel 8.6, Webressourcen, verwendet und mit CSS und Bildern in der Beispielanwendung „ratenumber-jsf“ falsch ausgeführt wird .
Jesper