我已完成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和图像)资源的最佳方法是什么?
答案 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。
最终,这些资源可以在任何地方获得,无需摆弄相对路径:
<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>
HeadRenderer
如果您正在使用PrimeFaces,其HeadRenderer
将清除默认的<h:head>
脚本排序,如上所述。您基本上被迫通过PrimeFaces特定的<f:facet name="first|middle|last">
强制执行订单,这可能最终会出现混乱和“无法模板”的代码。您可能需要按this answer。
您甚至可以将资源打包到JAR文件中。另请参阅Structure for multiple JSF projects with shared code。
您可以在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>
通过#{resource}
加载的第三方CSS文件反过来引用字体和/或图片可能需要更改为使用UnmappedResourceHandler
表达式,如上一节所述,否则需要/resources
安装是为了能够为使用JSF的人提供服务。另见a.o. Bootsfaces page shows up in browser without any styling和How to use Font Awesome 4.x CSS file with JSF? Browser can't find font files。
如果您打算通过将整个/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和图像。