实际上,网络上所有那些常用的内容/文件类型如“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" />
应该很清楚,它基本上表示所有这些资源共同属于的公共库/模块/主题名称。
更容易识别
这样就更容易指定和区分这些资源属于和/或来自哪里。假设你在自己的webapp中有一个PrimeFaces . CSS资源,其中你重写/微调了PrimeFaces的一些默认CSS;如果PrimeFaces没有为自己的PrimeFaces .css使用库名,那么PrimeFaces自己的库名将不会被加载,而是由web应用程序提供的库名,这将破坏外观。
Also, when you're using a custom ResourceHandler, you can also apply more finer grained control over resources coming from a specific library when library is used the right way. If all component libraries would have used "js" for all their JS files, how would the ResourceHandler ever distinguish if it's coming from a specific component library? Examples are OmniFaces CombinedResourceHandler and GraphicResourceHandler; check the createResource() method wherein the library is checked before delegating to next resource handler in chain. This way they know when to create CombinedResource or GraphicResource for the purpose.
值得注意的是,RichFaces做错了。它根本没有使用任何库,而是在上面自制了另一个资源处理层,因此不可能通过编程来识别RichFaces资源。这正是OmniFaces CombinedResourceHander必须引入基于反射的黑客的原因,以便使它能够与RichFaces资源一起工作。
你自己的网络应用
你自己的web应用并不一定需要一个资源库。你最好把它省略掉。
<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展示源代码。
或者,当你想在多个webapp上共享相同的资源,并基于这个答案中的相同示例创建了一个“公共”项目,该项目反过来作为JAR嵌入到webapp的/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" />
库版本
另一个主要优势是,您可以对自己的webapp提供的资源应用资源库版本控制(这不适用于嵌入在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将根据数值排序规则自动从最高版本号提供资源。
因此,当复制/重命名资源/default/1_0/*文件夹到资源/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="" />
这将迫使web浏览器直接从服务器请求资源,而不是从缓存中显示具有相同名称的资源,当参数发生变化的URL第一次被请求时。这样,当最终用户需要检索更新的CSS/JS资源时,就不需要执行硬刷新(Ctrl+F5等)。
请注意,对于JAR文件中包含的资源,库版本控制是不可能的。您需要一个自定义的ResourceHandler。请参见如何对jar中的资源使用JSF版本控制。
参见:
JSF资源版本控制
静态资源缓存
结构,用于具有共享代码的多个JSF项目
JSF 2.0规范-第2.6章资源处理