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

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

问题描述

JSF <h:outputStylesheet> <h:outputScript> <h:graphicImage> 组件具有library属性.这是什么,应该如何使用?网络上有很多示例使用它们,如下所示,根据所使用的标签,将常见内容/文件类型cssjsimg(或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输出也有些不同.给定/contextnameFacesServlet的上下文路径(在*.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实现,例如 Mojarra PrimeFaces OmniFaces 使用它.他们中没有人以这种方式使用资源库.他们使用它(由 @ResourceDependency

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 GraphicResourceHandler ;检查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 必须引入

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应用程序上共享相同的资源,并根据与

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

这将生成以下HTML,其库版本为v参数:

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

这将强制Web浏览器在第一次请求具有更改的参数的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天全站免登陆