如何在Facelets模板中引用CSS / JS /图像资源?

问题描述 投票:52回答:4

我做过tutorial about Facelets templating

现在我尝试创建一个与模板不在同一目录中的页面。我有页面样式的问题,因为样式用相对路径引用,如下所示:

<link rel="stylesheet" href="style_resource_path.css" />

我可以从/开始使用绝对引用:

<link rel="stylesheet" href="/project_root_path/style_resource_path.css" />

但是,当我将应用程序移动到不同的环境时,这将给我带来麻烦。

所以我想知道在Facelets中引用CSS(以及JS和图像)资源的最佳方法是什么?

jsf resources jsf-2 facelets templating
4个回答
106
投票

介绍

正确的JSF 2.x方式是使用<h:outputStylesheet><h:outputScript><h:graphicImage>name引用相对于webapp的/resources文件夹的路径。这样您就不必像在JSF 1.x中那样担心上下文路径。另见How to include CSS relative to context path in JSF 1.x?

文件夹结构

将CSS / JS /图像文件放在公共webcontent的/resources文件夹中,如下所示(如果不存在,则创建一个与/WEB-INF/META-INF相同的级别)。

WebContent
 |-- resources
 |    |-- css
 |    |    |-- other.css
 |    |    `-- style.css
 |    |-- js
 |    |    `-- script.js
 |    `-- images
 |         |-- background.png
 |         |-- favicon.ico
 |         `-- logo.png
 |-- META-INF
 |    `-- MANIFEST.MF
 |-- WEB-INF
 |    |-- faces-config.xml
 |    `-- web.xml
 |-- page.xhtml
 :

在Maven的情况下,它应该在/main/webapp/resources中,因此不是/main/resources(那些用于Java资源(properties / xml / text / config文件),它们必须最终在运行时类路径中,而不是在webcontent中)。另见Maven and JSF webapp structure, where exactly to put JSF resources

在Facelets中引用

最终,这些资源可以在任何地方获得,无需摆弄相对路径:

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

name属性必须表示相对于/resources文件夹的完整路径。它不需要从/开始。只要您没有开发像PrimeFaces这样的组件库或由多个webapp共享的公共模块JAR文件,就不需要library属性。

您可以在任何地方引用<h:outputStylesheet>,也可以在模板客户端的<ui:define>中引用,而无需额外的<h:head>。它将通过主模板的<h:head>组件自动结束生成的<head>

<ui:define name="...">
    <h:outputStylesheet name="css/style.css" />
    ...
</ui:define>

您也可以在任何地方引用<h:outputScript>,但默认情况下它会在您声明它的地方的HTML中结束。如果你希望它通过<head>结束在<h:head>,那么添加target="head"属性。

<ui:define name="...">
    <h:outputScript name="js/script.js" target="head" />
    ...
</ui:define>

或者,如果你希望它最终在<body>的末尾(在</body>之前,所以例如window.onload$(document).ready()等没有必要)通过<h:body>,然后添加target="body"属性。

<ui:define name="...">
    <h:outputScript name="js/script.js" target="body" />
    ...
</ui:define>

PrimeFaces HeadRenderer

如果你正在使用PrimeFaces,它的HeadRenderer将如上所述弄乱默认的<h:head>脚本排序。您基本上被迫通过PrimeFaces特定的<f:facet name="first|middle|last">强制执行订单,这可能会导致混乱和“无法模板”的代码。你可能想要关闭它,如this answer中所述。

在JAR中打包

您甚至可以将资源打包到JAR文件中。另见Structure for multiple JSF projects with shared code

在EL中引用

您可以在EL中使用#{resource}映射让JSF基本上打印像/context/javax.faces.resource/folder/file.ext.xhtml?ln=library这样的资源URL,以便您可以将其用作例如CSS背景图片或favicon。唯一的要求是CSS文件本身也应该作为JSF资源提供,否则EL表达式将不会被评估。另见How to reference JSF image resource as CSS background image url

.some {
    background-image: url("#{resource['images/background.png']}");
}

这是@import的例子。

@import url("#{resource['css/other.css']}");

这是favicon的例子。另见Add favicon to JSF project and reference it in <link>

<link rel="shortcut icon" href="#{resource['images/favicon.ico']}" />

如果您使用的是SCSS编译器(例如Sass Compiler Plugin for Maven),请记住SCSS处理器可能会将#解释为特殊字符。在这种情况下,您需要使用\来逃避它。

.some {
    background-image: url("\#{resource['images/background.png']}");
}

引用第三方CSS文件

通过<h:outputStylesheet>加载的第三方CSS文件反过来引用字体和/或图像可能需要更改为使用#{resource}表达式,如上一节所述,否则需要安装UnmappedResourceHandler才能为使用JSF的人提供服务。另见a.o. Bootsfaces page shows up in browser without any stylingHow to use Font Awesome 4.x CSS file with JSF? Browser can't find font files

隐藏在/ WEB-INF中

如果您打算通过将整个/resources文件夹移动到/WEB-INF来隐藏公共访问资源,那么您可以从JSF 2.2中选择性地通过新的web.xml上下文参数更改webcontent-relative路径,如下所示:

<context-param>
    <param-name>javax.faces.WEBAPP_RESOURCES_DIRECTORY</param-name>
    <param-value>/WEB-INF/resources</param-value>
</context-param>

在较旧的JSF版本中,这是不可能的。

See also:


7
投票

假设您正在运行Web应用程序的子目录中。你可以尝试这样:

 <link href="${facesContext.externalContext.requestContextPath}/css/style.css" rel="stylesheet" type="text/css"/>

'${facesContext.externalContext.requestContextPath}/'链接将帮助您立即返回上下文的根。

在相对URL中,前导斜杠/指向域根。因此,如果JSF页面例如由http://example.com/context/page.jsf请求,则CSS URL将绝对指向http://example.com/styles/decoration.css。要知道有效的相对URL,您需要知道JSF页面和CSS文件的绝对URL,并从另一个中提取一个。

假设您的CSS文件实际位于http://example.com/context/styles/decoration.css,那么您需要删除前导斜杠,使其相对于当前上下文(page.jsp之一):

<link rel="stylesheet" type="text/css" href="styles/decoration.css" />

2
投票

这些答案帮助我解决了同样的问题。虽然我使用SASS和GULP后问题更加复杂。

我不得不改变(请注意#前面的“\”。吞咽的可能副作用:

 <h:outputStylesheet library="my_theme" name="css/default.css"/>  

 background: $blue url("\#{resource['my_theme/images/background-homepage-h1.png']}");

0
投票

resourcehandlers.UnmappedResourceHandler有助于在/javax.faces.resource/*的URL模式上映射JSF资源。

对我来说,faces-config.xml中的这两个xml配置:org.omnifaces.resourcehandler.UnmappedResourceHandler

并在web.xml中:

<servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>/javax.faces.resource/*</url-pattern>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

帮助css和图像。

© www.soinside.com 2019 - 2024. All rights reserved.