JSF资源库有什么功能,应如何使用?


228

在JSF <h:outputStylesheet><h:outputScript><h:graphicImage>组件具有library属性。这是什么,应该如何使用?网上有很多示例,它们使用以下示例,它们具有常见的内容/文件类型cssjs并且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输出也有些不同。给定的上下文路径/contextnameFacesServletURL模式的映射*.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="" />

后者使用URI路径中的库名称生成以下HTML:

<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那么,该属性到底有多有用?

Answers:


256

实际上,网络上使用“ js”,“ css”,“ img”等常见内容/文件类型作为库名称的所有这些示例都是令人误解的

现实世界中的例子

首先,让我们看一下现有的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" />

应该清楚的是,它基本上代表了所有这些资源共同所属的公共库/模块/主题名称

更容易识别

这样,指定和区分那些资源属于和/或来自何处变得容易得多。想象一下,您碰巧primefaces.css在自己的Web应用程序中有一个资源,其中您要覆盖/微调PrimeFaces的一些默认CSS;如果PrimeFaces自己没有使用库名primefaces.css,则不会加载PrimeFaces自己的库名,而是由webapp提供的库名,这会破坏外观。

同样,当您使用custom时ResourceHandler,如果使用正确,则还可以对来自特定库的资源应用更精细的控制library。如果所有组件库的所有JS文件都将使用“ js”,那么如何ResourceHandler区分它是否来自特定组件库呢?示例包括OmniFaces CombinedResourceHandlerGraphicResourceHandler; createResource()在委托给链中的下一个资源处理程序之前,请检查对库进行检查的方法。这样,他们便知道何时创建CombinedResourceGraphicResource目的。

值得注意的是RichFaces做错了。它根本不使用任何library资源,而是在其上自制了另一个资源处理层,因此无法以编程方式标识RichFaces资源。这正是OmniFaces CombinedResourceHander必须引入基于反射的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展示柜源代码

或者,如果您想在多个Web应用程序上共享相同的资源,并根据与该答案相同的示例为其创建了一个“公共”项目,该项目又作为JAR嵌入在Web应用程序的中/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" />

库版本控制

另一个主要优点是,您可以在自己的Web应用程序提供的资源上以正确的方式应用资源库版本控制(这不适用于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时,这将迫使Web浏览器直接从服务器请求资源,而不是从缓存中显示具有相同名称的资源。这样,最终用户在需要检索更新的CSS / JS资源时就不需要进行强制刷新(Ctrl + F5等)。

请注意,JAR文件中包含的资源无法进行库版本控制。您需要自定义ResourceHandler。另请参见如何对jar中的资源使用JSF版本控制

也可以看看:


2
图书馆可以使用EL吗?因此,如果我今天想拥有一个资源/默认值和一个资源/ feelingFroggyToday,则可以执行诸如library =“#{someLibraryHere}”的映射操作,将someLibraryHere映射到我选择的库中,而不必每次都依赖于将资源目录重命名为更高版本我想改变他们。
gebuh 2012年

当您说library = admin或libray = layout时,资源文件夹中的那些文件夹(admin和layout)吗?
Koray Tugay 2013年

嗯 非常有趣的Balus。我在加载主题文件时显示为空的Web应用程序中遇到问题。仅在进行各种重新部署之后(在JBOSS EAP中),才会发生这种情况。CSS网址是这样的:/javax.faces.resource/css/theme.css.xhtml?ln=default&v=3_3_0_130416,它是这样声明的:<h:outputStylesheet库=“ default” name =“ css / theme。 css“ target =” head“ />。也许这个问题与版本问题有关?
Ricardo Vila 2015年

2
libraryMojarra 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。不幸的是,甚至Oracle自己的Java EE 7教程也通过css8.6 Web Resources一章中使用库名来给出错误的示例,并在guessnumber-jsf示例应用程序中对css和image进行了错误处理。
Jesper
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.