Для чего нужна библиотека ресурсов JSF и как ее использовать?

228

JSF <h:outputStylesheet>, <h:outputScript>и <h:graphicImage>компоненты имеют libraryатрибут. Что это такое и как это следует использовать? Есть много примеров в Интернете , которые используют его как следует с обычным типом контента / файлов css, jsи img(или image) в качестве имени библиотеки в зависимости от используемого тега:

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

Чем это полезно? libraryЗначение в этих примерах , как представляется, просто повторяя то , что уже было представлено именем тега. Для него <h:outputStylesheet>он основан на названии тега, уже очевидно, что оно представляет собой «библиотеку CSS». Какая разница со следующим, который также работает так же?

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

Кроме того, сгенерированный вывод HTML немного отличается. С учетом пути к контексту /contextnameи FacesServletсопоставления с шаблоном URL-адреса *.xhtmlпервый формирует следующий HTML-код с именем библиотеки в качестве параметра запроса:

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

В то время как последний генерирует следующий HTML-код с именем библиотеки только в пути 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="" />

Последний подход в ретроспективе также имеет больший смысл, чем первый. Как именно этот libraryатрибут тогда полезен?

BalusC
источник

Ответы:

256

На самом деле, все эти примеры в Интернете, где в качестве имени библиотеки используется общий тип содержимого / файла, такой как «js», «css», «img» и т. Д., Вводят в заблуждение .

Примеры из реального мира

Для начала давайте посмотрим, как его используют существующие реализации JSF, такие как Mojarra и MyFaces, и библиотеки компонентов JSF, такие как PrimeFaces и OmniFaces . Никто из них не использует библиотеки ресурсов таким образом. Они используют его (под одеялом, @ResourceDependencyили UIViewRoot#addComponentResource()) следующим образом:

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

Должно стать ясно, что оно в основном представляет общее имя библиотеки / модуля / темы, к которому обычно относятся все эти ресурсы.

Более простая идентификация

Таким образом, намного проще указать и различить, откуда эти ресурсы принадлежат и / или откуда. Представьте, что у вас есть primefaces.cssресурс в вашем собственном веб-приложении, в котором вы переопределяете / настраиваете некоторые CSS по умолчанию PrimeFaces; если бы PrimeFaces не использовал имя библиотеки для собственного имени primefaces.css, то собственное имя PrimeFaces не будет загружено, а вместо этого будет предоставлено веб-приложением, что нарушит внешний вид.

Кроме того, когда вы используете пользовательскую настройку ResourceHandler, вы также можете применять более точный контроль над ресурсами, поступающими из определенной библиотеки, при libraryправильном использовании. Если бы все библиотеки компонентов использовали бы «js» для всех своих файлов JS, как бы они ResourceHandlerотличались, если бы они исходили из библиотеки конкретных компонентов? Примерами являются OmniFaces CombinedResourceHandlerи GraphicResourceHandler; проверьте createResource()метод, в котором библиотека проверяется перед делегированием следующему обработчику ресурса в цепочке. Таким образом, они знают, когда создавать CombinedResourceили GraphicResourceдля этой цели.

Следует отметить, что RichFaces сделал это неправильно. Он вообще не использовался libraryи сам по себе создал еще один уровень обработки ресурсов, поэтому невозможно программно идентифицировать ресурсы RichFaces. Именно по этой причине OmniFaces CombinedResourceHander пришлось ввести взлом на основе отражений , чтобы заставить его работать в любом случае с ресурсами RichFaces.

Ваш собственный веб-приложение

Ваше собственное веб-приложение не обязательно нуждается в библиотеке ресурсов. Вы бы лучше просто опустить это.

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

Или, если вам действительно нужно иметь его, вы можете просто дать ему более разумное общее имя, такое как «default» или название какой-либо компании.

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

Или, когда ресурсы относятся к какому-либо основному шаблону Facelets, вы также можете дать ему имя шаблона, чтобы было легче связывать друг друга. Другими словами, это больше для самодокументированных целей. Например, в /WEB-INF/templates/layout.xhtmlфайле шаблона:

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

И /WEB-INF/templates/admin.xhtmlфайл шаблона:

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

Для примера из реального мира, проверьте исходный код витрины OmniFaces .

Или, если вы хотите использовать одни и те же ресурсы в нескольких веб-приложениях и создали для этого «общий» проект, основанный на том же примере, что и в этом ответе, который, в свою очередь, встроен в веб-приложение в виде JAR /WEB-INF/lib, то также укажите его как библиотеку. (имя свободно по вашему выбору; библиотеки компонентов, такие как OmniFaces и PrimeFaces, также работают таким образом):

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

Управление версиями библиотеки

Другое основное преимущество заключается в том, что вы можете правильно применять управление версиями библиотеки ресурсов к ресурсам, предоставляемым вашим собственным веб-приложением (это не работает для ресурсов, встроенных в JAR). Вы можете создать прямую дочернюю подпапку в папке библиотеки с именем в \d+(_\d+)*шаблоне для обозначения версии библиотеки ресурсов.

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

При использовании этой разметки:

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

Будет сгенерирован следующий HTML-код с версией библиотеки в качестве vпараметра:

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

Итак, если вы отредактировали / обновили какой-либо ресурс, все, что вам нужно сделать, это скопировать или переименовать папку версии в новое значение. Если у вас есть несколько папок версий, JSF ResourceHandlerбудет автоматически обслуживать ресурс с наибольшим номером версии в соответствии с числовыми правилами упорядочения.

Итак, при копировании / переименовании resources/default/1_0/*папки в resources/default/1_1/*подобное происходит:

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

Тогда последний пример разметки сгенерирует следующий 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="" />

Это заставит веб-браузер запрашивать ресурс прямо с сервера, а не показывать ресурс с тем же именем из кэша, когда URL с измененным параметром запрашивается впервые. Таким образом, конечные пользователи не обязаны выполнять полное обновление (Ctrl + F5 и т. Д.), Когда им нужно получить обновленный ресурс CSS / JS.

Обратите внимание, что управление версиями библиотеки невозможно для ресурсов, включенных в файл JAR. Тебе нужен кастом ResourceHandler. Смотрите также Как использовать управление версиями JSF для ресурсов в jar .

Смотрите также:

BalusC
источник
2
Можно ли использовать EL для библиотеки? Поэтому, если бы я хотел иметь resources / default и resources / feelFroggyToday, я мог бы сделать что-то вроде library = "# {someLibraryHere}", сопоставить someLibraryHere с моей выбранной библиотекой и не должен полагаться на переименование каталога ресурсов в более высокую версию каждый раз Я хотел изменить их.
Gebuh
Когда вы говорите, что library = admin или libray = layout, находятся ли эти папки (admin и layout) в папке ресурсов?
Корай Тугай
Ммм. Очень интересный Балус. Я столкнулся с проблемой в веб-приложении, где файл theme.css при загрузке пуст. Это происходит только после различных повторных развертываний (в JBOSS EAP). URL-адрес css выглядит следующим образом: /javax.faces.resource/css/theme.css.xhtml?ln=default&v=3_3_0_130416 и объявляется так: <h: outputStylesheet library = "default" name = "css / theme. css "target =" head "/>. Может быть, эта проблема связана с проблемами управления версиями?
Рикардо Вила
2
libraryИзменились ли разрешенные символы для значения или чего-то связанного с ним между моджаррой 2.2.5 (2.2.5-jbossorg-3, wildfly 8.0) и 2.2.11 (2.2.11-jbossorg-1)? Я не могу найти что-нибудь в примечаниях к выпуску. См stackoverflow.com/questions/35719808/...
Kukeltje
3
Спасибо @BalusC. К сожалению, даже в собственном учебном руководстве по Java EE 7 от Oracle приведен неправильный пример с использованием имени библиотеки cssв главе 8.6 Веб-ресурсы и неправильной работы с css и изображениями в примере приложения guessnumber-jsf .
Джеспер