什么是JSF资源库以及如何使用它?

时间:2012-08-16 13:38:19

标签: jsf jsf-2 resources

JSF <h:outputStylesheet><h:outputScript><h:graphicImage>组件具有library属性。这是什么以及如何使用它?网上有很多例子,它们使用如下公共内容/文件类型cssjsimg(或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输出略有不同。给定/contextnameFacesServlet的URL模式的上下文路径,前者生成以下HTML,其库名称为请求参数:

*.xhtml

虽然后者在URI的路径中生成以下带有库名称的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="" />

后一种方法事后也比前一种方法更有意义。 <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="" /> 属性究竟有用吗?

1 个答案:

答案 0 :(得分:246)

实际上,网络上的所有公共内容/文件类型如“js”,“css”,“img”等被用作库名称的例子都是误导性的。< / p>

真实世界的例子

首先,让我们看看现有的JSF实现如MojarraMyFaces以及JSF组件库如PrimeFacesOmniFaces如何使用它。他们中没有人以这种方式使用资源库。他们通过以下方式使用它(在@ResourceDependencyUIViewRoot#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" />

应该清楚它基本上代表公共库/模块/主题名称,其中所有这些资源通常都属于。

更容易识别

通过这种方式,可以更容易地指定和区分这些资源属于和/或来自何处。想象一下,您在自己的webapp中碰巧拥有primefaces.css资源,其中您正在覆盖/微调PrimeFaces的一些默认CSS;如果PrimeFaces没有为自己的primefaces.css使用库名,那么PrimeFaces自己的那个不会被加载,而是webapp提供的那个,这会破坏look'n'feel。

此外,当您使用自定义ResourceHandler时,如果以正确的方式使用library,您还可以对来自特定库的资源应用更精细的控制。如果所有组件库都为其所有JS文件使用了“js”,ResourceHandler如何区分它是否来自特定的组件库?示例是OmniFaces CombinedResourceHandlerGraphicResourceHandler;在委派给链中的下一个资源处理程序之前,检查其中已检查库的createResource()方法。通过这种方式,他们知道何时为此目的创建CombinedResourceGraphicResource

注意到RichFaces应该做错了。它根本没有使用任何library,并在其上自制了另一个资源处理层,因此无法以编程方式识别RichFaces资源。这就是为什么OmniFaces CombinedResourceHander必须引入a reflection-based hack以使其无论如何都能使用RichFaces资源的原因。

您自己的网络应用

您自己的webapp不一定需要资源库。你最好省略它。

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

或者,如果你真的需要一个,你可以给它一个更明智的通用名称,比如“默认”或一些公司名称。

<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 showcase source code

或者,当您想要在多个Web应用程序上共享相同的资源并基于与this answer中相同的示例为此创建“通用”项目时,该How to use JSF versioning for resources in jar又作为JAR嵌入到webapp的{ {1}},然后也将它作为库引用(名称可供您自由选择; OmniFaces和PrimeFaces等组件库也可以这样工作):

/WEB-INF/lib

库版本控制

另一个主要优点是您可以在您自己的webapp提供的资源上以正确的方式应用资源库版本控制(这不适用于嵌入在JAR中的资源)。您可以使用<h:outputStylesheet library="common" name="css/style.css" /> <h:outputScript library="common" name="js/script.js" /> <h:graphicImage library="common" name="img/logo.png" /> 模式中的名称在库文件夹中创建直接子子文件夹,以表示资源库版本。

\d+(_\d+)*

使用此标记时:

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

这将生成以下HTML,其库版本为<h:outputStylesheet library="default" name="css/style.css" /> <h:outputScript library="default" name="js/script.js" /> <h:graphicImage library="default" name="img/logo.png" /> 参数:

v

因此,如果您已编辑/更新了某些资源,那么您需要做的就是将版本文件夹复制或重命名为新值。如果您有多个版本文件夹,则JSF <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="" /> 将根据数字排序规则自动从最高版本号提供资源。

因此,将ResourceHandler文件夹复制/重命名为resources/default/1_0/*时,如下所示:

resources/default/1_1/*

然后最后一个标记示例将生成以下HTML:

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

这将强制webbrowser直接从服务器请求资源,而不是在第一次请求具有已更改参数的URL时从缓存中显示具有相同名称的资源。这样,当需要检索更新的CSS / JS资源时,endusers不需要进行硬刷新(Ctrl + F5等)。

请注意,JAR文件中包含的资源无法进行库版本控制。您需要自定义<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="" /> 。另请参阅JSF resource versioning

另见: