介绍
JSF 2.x 的正确方式是使用 <h:outputStylesheet>
, <h:outputScript>
和 <h:graphicImage>
,并使用相对于 webapp 的 /resources
文件夹的路径引用 name
。这样,您就不需要像在 JSF 1.x 中那样担心上下文路径。另请参见如何在 JSF 1.x 中相对于上下文路径包含 CSS?
文件夹结构
将 CSS/JS/图像文件放入公共 Web 内容的 /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/文本/配置文件),必须最终出现在运行时类路径中,而不是Web内容)。另请参见
Maven和JSF Web应用程序结构,在哪里放置JSF资源。
在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中。如果你希望它通过
<h:head>
最终出现在
<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基本上打印出一个资源URL,例如/context/javax.faces.resource/folder/file.ext.xhtml?ln=library
,这样你就可以将其用作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']}");
这是一个网站图标的示例。还可以查看
将网站图标添加到JSF项目中,并在<link>中引用它。
<link rel="shortcut icon" href="#{resource['images/favicon.ico']}" />
如果您使用SCSS编译器(例如Maven的Sass编译器插件),请注意SCSS处理器可能将#
解释为特殊字符。在这种情况下,您需要使用\
进行转义。
.some {
background-image: url("\#{resource['images/background.png']}");
}
引用第三方CSS文件
通过<h:outputStylesheet>
加载的第三方CSS文件,如果引用了字体和/或图像,则可能需要更改为使用先前部分中描述的#{resource}
表达式,否则需要安装UnmappedResourceHandler
以便能够使用JSF提供服务。另请参见Bootsfaces页面在浏览器中没有任何样式和如何使用Font Awesome 4.x CSS文件与JSF?浏览器找不到字体文件。
隐藏在/WEB-INF中
如果您打算通过将整个/resources
文件夹移动到/WEB-INF
来隐藏资源以防止公共访问,则可以自JSF 2.2起通过新的web.xml
上下文参数选择更改Web内容相关路径,方法如下:
<context-param>
<param-name>javax.faces.WEBAPP_RESOURCES_DIRECTORY</param-name>
<param-value>/WEB-INF/resources</param-value>
</context-param>
在旧版的JSF中,这是不可能的。
另请参阅:
url("#{resource['otbofaces:date-entry/calendar.gif']}")
非常有效,但我还没有找到任何可以在javascript文件中使用以获取正确资源位置的内容。 - mrswadge<ui:composition template="/templates/report.xhtml">
这样的操作,其中我的模板驻留在web/resources/templates/report.xhtml
,甚至利用库中的资源结构。但事实并非如此。 - YoYo