Для чего нужна библиотека ресурсов JSF и как ее использовать?
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
атрибут тогда полезен?
1 ответ
На самом деле, все эти примеры в Интернете, где в качестве имени библиотеки используется общий тип содержимого / файла, такой как "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&v=1_0" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&v=1_0"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&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&v=1_1" />
<script type="text/javascript" src="/contextname/javax.faces.resource/js/script.js.xhtml?ln=default&v=1_1"></script>
<img src="/contextname/javax.faces.resource/img/logo.png.xhtml?ln=default&v=1_1" alt="" />
Это заставит веб-браузер запрашивать ресурс прямо с сервера, а не показывать ресурс с тем же именем из кэша, когда URL с измененным параметром запрашивается впервые. Таким образом, конечным пользователям не требуется выполнять полное обновление (Ctrl+F5 и т. Д.), Когда им нужно получить обновленный ресурс CSS/JS.
Обратите внимание, что управление версиями библиотеки невозможно для ресурсов, включенных в файл JAR. Вам нужен кастом ResourceHandler
, Смотрите также Как использовать управление версиями JSF для ресурсов в jar.