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

时间:2011-12-03 11:47:08

标签: jsf resources jsf-2 facelets templating

我已完成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和图像)资源的最佳方法是什么?

4 个答案:

答案 0 :(得分: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资源(属性/ 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这样的组件库或由多个Web应用程序共享的公共模块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这样的资源网址,以便您可以将其用作例如.some { background-image: url("#{resource['images/background.png']}"); } 。 CSS背景图片或favicon。唯一的要求是CSS文件本身也应该作为JSF资源提供,否则EL表达式将不会被评估。另请参阅How to reference JSF image resource as CSS background image url

@import

这是@import url("#{resource['css/other.css']}"); 示例。

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

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

#

如果您使用的是SCSS编译器(例如Sass Compiler Plugin for Maven),请记住SCSS处理器可能会将\解释为特殊字符。在这种情况下,您需要使用.some { background-image: url("\#{resource['images/background.png']}"); } 转义它。

<h:outputStylesheet>

引用第三方CSS文件

通过#{resource}加载的第三方CSS文件反过来引用字体和/或图片可能需要更改为使用UnmappedResourceHandler表达式,如上一节所述,否则需要/resources安装是为了能够为使用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

如果您打算通过将整个/WEB-INF文件夹移动到web.xml来隐藏公共访问资源,那么您可以选择通过新的{{1}来更改Web内容相对路径上下文参数如下:

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

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

另见:

答案 1 :(得分:7)

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

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

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

在相对URL中,前导斜杠/指向域根。因此,如果http://example.com/context/page.jsf请求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 :(得分:2)

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

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

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

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

答案 3 :(得分:0)

resourcehandlers.UnmappedResourceHandler帮助将JSF资源映射到/javax.faces.resource/*的URL模式上。

对我来说,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和图像。