实际上,网络上所有那些将“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
在自己的 web 应用程序中有一个资源,您正在覆盖/微调 PrimeFaces 的一些默认 CSS;如果 PrimeFaces 不使用自己的库名称primefaces.css
,则不会加载 PrimeFaces 自己的库名称,而是加载 webapp 提供的库名称,这会破坏外观。
此外,当您使用 custom 时ResourceHandler
,您还可以在正确使用时对来自特定库的资源应用更细粒度的控制library
。如果所有组件库都对所有 JS 文件使用“js”,那么如何ResourceHandler
区分它是否来自特定组件库?例如 OmniFacesCombinedResourceHandler
和GraphicResourceHandler
; 检查createResource()
在委派给链中的下一个资源处理程序之前检查库的方法。这样他们就知道何时创建CombinedResource
或GraphicResource
用于目的。
应该注意的是 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 展示源代码。
或者,当您想在多个 webapps 上共享相同的资源并基于与此答案中相同的示例创建一个“通用”项目时,该项目又作为 JAR 嵌入 webapp's/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 中的资源)。您可以在 library 文件夹中创建一个直接子文件夹,并在\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="" />
因此,如果您编辑/更新了某些资源,那么您需要做的就是将版本文件夹复制或重命名为新值。如果您有多个版本文件夹,则 JSFResourceHandler
将根据数字排序规则自动从最高版本号开始提供资源。
因此,当复制/重命名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 时,这将强制 Web 浏览器直接从服务器请求资源,而不是从缓存中显示具有相同名称的资源。这样,最终用户在需要检索更新的 CSS/JS 资源时不需要进行硬刷新(Ctrl+F5 等)。
请注意,对于包含在 JAR 文件中的资源,库版本控制是不可能的。你需要一个自定义的ResourceHandler
. 另请参阅如何对 jar 中的资源使用 JSF 版本控制。
也可以看看: