实际上,网络上所有将常见的内容/文件类型如“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" />
很明显,它基本上代表了所有这些资源通常属于的公共库/模块/主题名称。
更易于识别
这样做可以更轻松地指定和区分资源所属和/或来自哪里。想象一下,你在自己的Web应用程序中有一个primefaces.css
资源,在其中覆盖/微调PrimeFaces的默认CSS;如果PrimeFaces没有为其自己的primefaces.css
使用库名称,那么不会加载PrimeFaces自己的文件,而是加载Web应用程序提供的文件,从而破坏外观和感觉。
此外,当您使用自定义ResourceHandler
时,如果正确使用library
,还可以对来自特定库的资源应用更精细化的控制。如果所有组件库都使用"js"作为其所有JS文件的库名称,那么ResourceHandler
怎样才能区分它是否来自特定的组件库呢?这些示例包括OmniFaces的CombinedResourceHandler
和GraphicResourceHandler
;请参阅createResource()
方法,其中检查了库以便在链中委托给下一个资源处理程序之前进行处理。这样他们就知道何时为特定的目的创建CombinedResource
或GraphicResource
。
需要注意的是,RichFaces做错了。它根本没有使用任何library
,而是自制了另一种资源处理层,因此无法以编程方式识别RichFaces资源。这正是OmniFaces CombinedResourceHander
不得不引入反射式黑客的原因,以使其可以与RichFaces资源一起正常工作。
您自己的Web应用程序
您自己的Web应用程序不一定需要资源库。最好省略它。
<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应用程序之间共享相同资源并已经创建了一个基于与这个答案中相同示例的“common”项目时,将其作为库引用(名称可自由选择;组件库如OmniFaces和PrimeFaces也是这样做的):将其嵌入到web应用程序的/WEB-INF/lib
中。
<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" />
使用库版本作为v
参数将生成以下HTML:
<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首次请求带有更改参数的资源时,这将强制网络浏览器直接从服务器请求资源,而不是显示具有相同名称的缓存中的资源。这样,当需要检索更新的CSS / JS资源时,最终用户无需进行硬刷新(Ctrl + F5等)。
请注意,对于嵌入JAR文件中的资源,无法进行库版本控制,您需要使用自定义ResourceHandler
。请参见How to use JSF versioning for resources in jar。
另请参阅:
library
的允许字符或与其相关的内容在 mojarra 2.2.5(2.2.5-jbossorg-3,wildfly 8.0)和 2.2.11(2.2.11-jbossorg-1)之间是否有更改?我似乎在发布说明中找不到任何信息。请参见https://dev59.com/qpTfa4cB1Zd3GeqPTJxd。 - Kukeltjecss
的错误示例,并在[guessnumber-jsf示例应用程序]中处理css和图像时出现问题。 - Jesper