首页 文章

什么是JSF资源库以及如何使用它?

提问于
浏览
217

JSF <h:outputStylesheet><h:outputScript><h:graphicImage>组件具有 library 属性 . 这是什么以及应该如何使用? Web上有很多示例,它们使用如下公共内容/文件类型 cssjsimg (或 image )作为库名,具体取决于所使用的标记:

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

它有用吗?这些示例中的 library 值似乎只是重复标记名称已经表示的内容 . 对于 <h:outputStylesheet> 它's based on the tag name already obvious that it represents a 418105 . What'与下面的区别也是同样的方式?

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

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

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

而后者在URI的路径中生成以下带有库名的HTML:

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

1 回答

  • 243

    实际上,Web上的所有这些示例都是 misleading ,其中公共内容/文件类型如"js","css","img"等被用作库名 .

    真实世界的例子

    首先,让我们看一下现有的JSF实现如MojarraMyFaces以及JSF组件库如PrimeFacesOmniFaces如何使用它 . 他们中没有人以这种方式使用资源库 . 他们通过以下方式使用它(在封面下,通过@ResourceDependencyUIViewRoot#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 资源,其中're overriding/finetuning some default CSS of PrimeFaces; if PrimeFaces didn' t使用库名称为自己的 primefaces.css ,然后PrimeFaces拥有一个不会't be loaded, but instead the webapp-supplied one, which would break the look' n'feel .

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

    值得注意的是,RichFaces做错了 . 它根本没有使用任何 library 并且在它上面自制了另一个资源处理层,而's therefore impossible to programmatically identify RichFaces resources. That'正好是OmniFaces CombinedResourceHander必须引入a reflection-based 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 showcase source code .

    或者,当您想要在多个Web应用程序上共享相同的资源并基于与this answer中相同的示例创建"common"项目时,该项目又作为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&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 将根据数字排序规则自动从最高版本号提供资源 .

    因此,将 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&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等) .

    请注意,JAR文件中包含的资源无法进行库版本控制 . 你需要一个自定义 ResourceHandler . 另见How to use JSF versioning for resources in jar .

    另见:

相关问题