Do czego służy biblioteka zasobów JSF i jak z niej korzystać?

228

JSF <h:outputStylesheet>, <h:outputScript>a <h:graphicImage>elementy mają libraryatrybut. Co to jest i jak należy z tego korzystać? Istnieje wiele przykładów w sieci, które używają go w następujący sposób z typem wspólny content / plik css, jsi img(lub image) jako nazwy biblioteki w zależności od używanego tagu:

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

Jak to jest przydatne? libraryWartość w tych przykładach wydaje się być po prostu powtarzając co jest już reprezentowany przez nazwę znacznika. W przypadku, <h:outputStylesheet>gdy jest oparty na nazwie znacznika, jest już oczywiste, że reprezentuje „bibliotekę CSS”. Jaka jest różnica z następującymi, które również działają w ten sam sposób?

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

Ponadto wygenerowany wynik HTML jest nieco inny. Biorąc pod uwagę ścieżkę kontekstu /contextnamei FacesServletodwzorowanie na wzorzec adresu URL *.xhtml, ten pierwszy generuje następujący kod HTML z nazwą biblioteki jako parametrem żądania:

<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="" />

Podczas gdy ten ostatni generuje następujący kod HTML z nazwą biblioteki tylko na ścieżce identyfikatora URI:

<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="" />

To drugie podejście ma z perspektywy czasu również więcej sensu niż poprzednie. Jak dokładnie ten libraryatrybut jest przydatny?

BalusC
źródło

Odpowiedzi:

256

W rzeczywistości wszystkie te przykłady w Internecie, w których typowa zawartość / typ pliku, taki jak „js”, „css”, „img” itp. Są używane jako nazwa biblioteki, wprowadzają w błąd .

Przykłady ze świata rzeczywistego

Na początek przyjrzyjmy się, w jaki sposób wykorzystują je istniejące implementacje JSF, takie jak Mojarra i MyFaces, oraz biblioteki komponentów JSF, takie jak PrimeFaces i OmniFaces . Żadna z nich nie korzysta w ten sposób z bibliotek zasobów. Używają go (pod przykryciem, przez @ResourceDependencylub UIViewRoot#addComponentResource()) w następujący sposób:

<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" />

Powinno stać się jasne, że zasadniczo reprezentuje wspólną nazwę biblioteki / modułu / motywu, do której zwykle należą wszystkie te zasoby.

Łatwiejsza identyfikacja

W ten sposób o wiele łatwiej jest określić i odróżnić, skąd pochodzą te zasoby i / lub jakie pochodzą. Wyobraź sobie, że primefaces.cssakurat masz zasób we własnej aplikacji internetowej, w którym zastępujesz / dostosowujesz domyślny CSS PrimeFaces; jeśli PrimeFaces nie użyłby własnej nazwy biblioteki primefaces.css, to własna PrimeFaces nie zostałaby załadowana, ale zamiast tego dostarczona przez aplikację internetową, co zepsułoby wygląd i styl.

Ponadto, gdy korzystasz z niestandardowego ResourceHandler, możesz również zastosować bardziej szczegółową kontrolę nad zasobami pochodzącymi z określonej biblioteki, gdy libraryjest używana we właściwy sposób. Gdyby wszystkie biblioteki komponentów używały „js” dla wszystkich swoich plików JS, jak by się ResourceHandlerkiedykolwiek rozróżniało, gdyby pochodziło z konkretnej biblioteki komponentów? Przykładami są OmniFaces CombinedResourceHandleri GraphicResourceHandler; sprawdź createResource()metodę, w której biblioteka jest sprawdzana przed delegowaniem do następnego modułu obsługi zasobów w łańcuchu. W ten sposób wiedzą, kiedy stworzyć CombinedResourcelub GraphicResourcew jakim celu.

Należy zauważyć, że RichFaces zrobił to źle. W ogóle go nie użył libraryi dokonał homebrew kolejnej warstwy obsługi zasobów, dlatego nie można programowo zidentyfikować zasobów RichFaces. To jest dokładnie powód, dla którego OmniFaces CombinedResourceHander musiał wprowadzić hack oparty na odbiciach , aby mimo to mógł działać z zasobami RichFaces.

Twoja własna aplikacja internetowa

Twoja aplikacja internetowa niekoniecznie potrzebuje biblioteki zasobów. Lepiej to po prostu pomiń.

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

Lub, jeśli naprawdę musisz go mieć, możesz po prostu nadać mu bardziej sensowną wspólną nazwę, na przykład „default” lub nazwę firmy.

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

Lub, gdy zasoby są specyficzne dla jakiegoś głównego szablonu Facelets, możesz również nadać mu nazwę szablonu, aby łatwiej było się ze sobą powiązać. Innymi słowy, jest to bardziej do celów samodokumentowania. Np. W /WEB-INF/templates/layout.xhtmlpliku szablonu:

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

I /WEB-INF/templates/admin.xhtmlplik szablonu:

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

Na przykład w świecie rzeczywistym sprawdź kod źródłowy OmniFaces .

Lub, jeśli chcesz udostępnić te same zasoby w wielu aplikacjach internetowych i utworzyłeś dla tego „wspólny” projekt na podstawie tego samego przykładu, co w tej odpowiedzi, która z kolei jest osadzona jako JAR w aplikacjach internetowych /WEB-INF/lib, następnie określ ją jako bibliotekę (nazwa jest dowolna; biblioteki komponentów, takie jak OmniFaces i PrimeFaces, również działają w ten sposób):

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

Wersjonowanie bibliotek

Inną główną zaletą jest to, że można zastosować odpowiednią wersję biblioteki zasobów do zasobów udostępnianych przez własną aplikację internetową (nie działa to w przypadku zasobów osadzonych w pliku JAR). Możesz utworzyć bezpośredni podfolder podrzędny w folderze biblioteki z nazwą we \d+(_\d+)*wzorcu, oznaczającą wersję biblioteki zasobów.

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

Podczas korzystania z tego znacznika:

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

Spowoduje to wygenerowanie następującego kodu HTML z wersją biblioteki jako vparametrem:

<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="" />

Jeśli więc edytowałeś / aktualizowałeś jakiś zasób, wszystko, co musisz zrobić, to skopiować folder wersji lub zmienić jego nazwę na nową wartość. Jeśli masz wiele folderów wersji, JSF ResourceHandlerautomatycznie obsłuży zasób od najwyższego numeru wersji, zgodnie z numerycznymi zasadami porządkowania.

Tak więc podczas kopiowania / zmiany nazwy resources/default/1_0/*folderu na resources/default/1_1/*podobne:

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

Następnie ostatni przykład znaczników wygenerowałby następujący kod HTML:

<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="" />

Zmusi to przeglądarkę internetową do żądania zasobu bezpośrednio z serwera zamiast pokazywania zasobu o tej samej nazwie z pamięci podręcznej, gdy po raz pierwszy zostanie zażądany adres URL ze zmienionym parametrem. W ten sposób użytkownicy końcowi nie muszą przeprowadzać twardego odświeżania (Ctrl + F5 itd.), Gdy muszą pobrać zaktualizowany zasób CSS / JS.

Należy pamiętać, że wersjonowanie bibliotek nie jest możliwe w przypadku zasobów zawartych w pliku JAR. Potrzebujesz zwyczaju ResourceHandler. Zobacz także Jak używać wersjonowania JSF dla zasobów w jar .

Zobacz też:

BalusC
źródło
2
Czy możliwe jest użycie EL do biblioteki? Więc jeśli chciałbym mieć zasoby / domyślne i zasoby / feelFroggyToday, mógłbym zrobić coś takiego jak biblioteka = "# {someLibraryHere}" mapować someLibraryHere do mojej wybranej biblioteki i nie musiałbym polegać na zmianie nazwy katalogu zasobów na wyższą wersję za każdym razem Chciałem je zmienić.
gebuh,
Kiedy mówisz, że biblioteka = admin lub libray = layout, czy te foldery (admin i layout) znajdują się w folderze zasobów?
Koray Tugay
Umm. Bardzo interesujący Balus. Mam problem z aplikacją internetową, w której plik theme.css jest pusty podczas ładowania. Dzieje się tak dopiero po różnych wdrożeniach (w JBOSS EAP). Adres URL css jest następujący: /javax.faces.resource/css/theme.css.xhtml?ln=default&v=3_3_0_130416 i jest deklarowany w ten sposób: <h: outputStylesheet library = "default" name = "css / theme. css "target =" head "/>. Może ten problem jest związany z problemami z wersją?
Ricardo Vila
2
Czy dozwolone znaki dla wartości librarylub czegoś z nią związanego zmieniły się między mojarra 2.2.5 (2.2.5-jbossorg-3, wildfly 8.0) a 2.2.11 (2.2.11-jbossorg-1)? Nie mogę znaleźć niczego w przypisach do wydania. Zobacz stackoverflow.com/questions/35719808/…
Kukeltje
3
Dzięki @BalusC. Niestety nawet własny samouczek Java EE 7 firmy Oracle podaje zły przykład, używając nazwy biblioteki cssw rozdziale 8.6 Zasoby sieciowe i robiąc to źle z css i obrazami w przykładowej aplikacji guessnumber-jsf .
Jesper