JSF 资源库的用途是什么,应该如何使用? [英] What is the JSF resource library for and how should it be used?

查看:33
本文介绍了JSF 资源库的用途是什么,应该如何使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JSF <h:outputStylesheet>, 组件有一个 library 属性.这是什么,应该如何使用?网络上有很多使用它的示例,它们使用常见的内容/文件类型 cssjsimg(或 imgcode>image) 作为库名,取决于所使用的标签:

The JSF <h:outputStylesheet>, <h:outputScript> and <h:graphicImage> components have a library attribute. What is this and how should this be used? There are a lot of examples on the web which use it as follows with the common content/file type css, js and img (or image) as library name depending on the tag used:

<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 库".与以下内容相同的内容有什么区别?

How is it useful? The library value in those examples seems to be just repeating whatever is already been represented by the tag name. For a <h:outputStylesheet> it's based on the tag name already obvious that it represents a "CSS library". What's the difference with the following which also just works the same way?

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

另外,生成的 HTML 输出有点不同.给定 /contextname 的上下文路径和 FacesServlet 映射到 *.xhtml 的 URL 模式,前者生成以下带有库名称的 HTML作为请求参数:

Also, the generated HTML output is a bit different. Given a context path of /contextname and FacesServlet mapping on an URL pattern of *.xhtml, the former generates the following HTML with the library name as request parameter:

<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="" />

而后者生成以下 HTML,库名称正好位于 URI 的路径中:

While the latter generates the following HTML with the library name just in the path of the URI:

<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 属性究竟有什么用?

The latter approach makes in hindsight also more sense than the former approach. How exactly is the library attribute then useful?

推荐答案

实际上,网络上的所有示例都使用了常见的内容/文件类型,如js"、css"、img"等因为图书馆名称具有误导性.

Actually, all of those examples on the web wherein the common content/file type like "js", "css", "img", etc is been used as library name are misleading.

首先,让我们看看现有的 JSF 实现,如 MojarraMyFaces 和 JSF 组件库,如 PrimeFacesOmniFaces 使用它.他们中没有人以这种方式使用资源库.他们使用它(在幕后,@ResourceDependencyUIViewRoot#addComponentResource()) 如下:

To start, let's look at how existing JSF implementations like Mojarra and MyFaces and JSF component libraries like PrimeFaces and OmniFaces use it. No one of them use resource libraries this way. They use it (under the covers, by @ResourceDependency or UIViewRoot#addComponentResource()) the following way:

<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" />

很明显,它基本上代表了所有这些资源通常所属的通用库/模块/主题名称.

It should become clear that it basically represents the common library/module/theme name where all of those resources commonly belong to.

通过这种方式,可以更轻松地指定和区分这些资源属于和/或来自何处.想象一下,您碰巧在自己的 web 应用程序中有一个 primefaces.css 资源,您正在其中覆盖/微调 PrimeFaces 的一些默认 CSS;如果 PrimeFaces 没有为其自己的 primefaces.css 使用库名称,那么 PrimeFaces 自己的库名称将不会被加载,而是 webapp 提供的库名称,这会破坏外观感觉.

This way it's so much easier to specify and distinguish where those resources belong to and/or are coming from. Imagine that you happen to have a primefaces.css resource in your own webapp wherein you're overriding/finetuning some default CSS of PrimeFaces; if PrimeFaces didn't use a library name for its own primefaces.css, then the PrimeFaces own one wouldn't be loaded, but instead the webapp-supplied one, which would break the look'n'feel.

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

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 做错了.它根本没有使用任何 library 并在其上自制了另一个资源处理层,因此不可能以编程方式识别 RichFaces 资源.这正是 OmniFaces CombinedResourceHander 不得不引入 一个基于反射的 hack 以便让它无论如何都能与 RichFaces 资源一起工作.

Noted should be that RichFaces did it wrong. It didn't use any library at all and homebrewed another resource handling layer over it and it's therefore impossible to programmatically identify RichFaces resources. That's exactly the reason why OmniFaces CombinedResourceHander had to introduce a reflection-based hack in order to get it to work anyway with RichFaces resources.

您自己的 web 应用程序不一定需要资源库.你最好省略它.

Your own webapp does not necessarily need a resource library. You'd best just omit it.

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

或者,如果你真的需要一个,你可以给它一个更合理的通用名称,比如默认"或一些公司名称.

Or, if you really need to have one, you can just give it a more sensible common name, like "default" or some company name.

<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 模板文件中:

Or, when the resources are specific to some master Facelets template, you could also give it the name of the template, so that it's easier to relate each other. In other words, it's more for self-documentary purposes. E.g. in a /WEB-INF/templates/layout.xhtml template file:

<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 展示源代码.

For a real world example, check the OmniFaces showcase source code.

或者,当您想在多个 web 应用程序上共享相同的资源并基于与 这个答案,它又作为 JAR 嵌入 webapp 的 /WEB-INF/lib,然后也将其作为库引用(名称可以自由选择;像 OmniFaces 和 PrimeFaces 这样的组件库也可以这样使用):

Or, when you'd like to share the same resources over multiple webapps and have created a "common" project for that based on the same example as in this answer which is in turn embedded as JAR in webapp's /WEB-INF/lib, then also reference it as library (name is free to your choice; component libraries like OmniFaces and PrimeFaces also work that way):

<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+)* 模式中使用名称来表示资源库版本.

Library versioning

Another main advantage is that you can apply resource library versioning the right way on resources provided by your own webapp (this doesn't work for resources embedded in a JAR). You can create a direct child subfolder in the library folder with a name in the d+(_d+)* pattern to denote the resource library version.

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:

This will generate the following HTML with the library version as v parameter:

<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 将根据数字排序规则自动从最高版本号开始提供资源.

So, if you have edited/updated some resource, then all you need to do is to copy or rename the version folder into a new value. If you have multiple version folders, then the JSF ResourceHandler will automatically serve the resource from the highest version number, according to numerical ordering rules.

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

So, when copying/renaming resources/default/1_0/* folder into resources/default/1_1/* like follows:

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

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

Then the last markup example would generate the following 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="" />

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

This will force the webbrowser to request the resource straight from the server instead of showing the one with the same name from the cache, when the URL with the changed parameter is been requested for the first time. This way the endusers aren't required to do a hard refresh (Ctrl+F5 and so on) when they need to retrieve the updated CSS/JS resource.

请注意,对于包含在 JAR 文件中的资源,库版本控制是不可能的.您需要一个自定义的 ResourceHandler.另请参阅如何对 jar 中的资源使用 JSF 版本控制.

Please note that library versioning is not possible for resources enclosed in a JAR file. You'd need a custom ResourceHandler. See also How to use JSF versioning for resources in jar.

  • JSF resource versioning
  • JSF2 Static resource caching
  • Structure for multiple JSF projects with shared code
  • JSF 2.0 specification - Chapter 2.6 Resource Handling

这篇关于JSF 资源库的用途是什么,应该如何使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆