如何在Facelets模板中引用CSS / JS / image资源?
我已经完成了关于Facelets模板的教程 。
现在我试着创build一个与模板不在同一个目录中的页面。 我遇到了页面样式的问题,因为样式被相对path引用,如下所示:
<link rel="stylesheet" href="style_resource_path.css" />
我可以使用以/
开头的绝对引用:
<link rel="stylesheet" href="/project_root_path/style_resource_path.css" />
但是当我将应用程序移到不同的上下文时,这会给我带来麻烦。
所以我想知道在Facelets中引用CSS(以及JS和图像)资源的最佳方式是什么?
介绍
正确的JSF 2.x方法是使用<h:outputStylesheet>
, <h:outputScript>
和<h:graphicImage>
来引用相对于webapp的/resources
文件夹的path。 这样,您就不必像在JSF 1.x中那样担心上下文path。 另请参见如何在JSF 1.x中包含相对于上下文path的CSS?
文件夹结构
将CSS / JS /图像文件放在public webcontent的/resources
文件夹中(如果不在/WEB-INF
和/META-INF
的相同级别,则创build一个)。
WebContent |-- META-INF |-- WEB-INF |-- resources | |-- css | | |-- other.css | | `-- style.css | |-- js | | `-- script.js | `-- images | |-- background.png | |-- favicon.ico | `-- logo.png |-- page.xhtml :
在Maven的情况下,它应该在/main/webapp/resources
,因此不是 /main/resources
(那些用于Java资源(properties / xml / text / config文件)的资源必须以运行时类path结束,而不是在webcontent中) 。 另请参阅Maven和JSF webapp结构,其中正是放置JSF资源的地方 。
在Facelets中引用
最终,这些资源可以在任何地方使用,无需摆弄相对path:
<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
文件夹的完整path。 它不需要以/
开头。 只要不开发像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>
<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">
来强制执行命令,最终可能会导致混乱和“无法模板化”的代码。 您可能需要按照此答案中的描述closures它。
在JAR中打包
您甚至可以将资源打包到JAR文件中。 另请参见具有共享代码的多个JSF项目的结构 。
在EL中引用
您可以在EL中使用#{resource}
映射让JSF基本上打印一个像/context/javax.faces.resource/folder/file.ext.xhtml?ln=library
这样的资源URL,以便您可以使用它作为例如CSS背景图像或图标。 唯一的要求是,CSS文件本身也应该作为一个JSF资源,否则ELexpression式不会评估。 另请参见如何将JSF图像资源引用为CSS背景图像url 。
.some { background-image: url("#{resource['images/background.png']}"); }
这里是@import
例子。
@import url("#{resource['css/other.css']}");
这里是favicon的例子。 另请参阅将图标添加到JSF项目,并在<link>中引用它 。
<link rel="shortcut icon" href="#{resource['images/favicon.ico']}" />
引用第三方CSS文件
通过<h:outputStylesheet>
加载第三方CSS文件,然后引用字体和/或图像可能需要改变为使用前面章节描述的#{resource}
expression式,否则需要安装一个UnmappedResourceHandler
以便能够为使用JSF的人提供服务。 另请参阅ao Bootsfaces页面显示在浏览器中,没有任何样式和如何使用JSF的Font Awesome 4.x CSS文件? 浏览器无法find字体文件 。
隐藏在/ WEB-INF中
如果您打算通过将整个/resources
文件夹移动到/WEB-INF
来隐藏公共访问/resources
,那么您可以通过JSF 2.2可选地通过新的web.xml
上下文参数更改webcontent相对path,如下所示:
<context-param> <param-name>javax.faces.WEBAPP_RESOURCES_DIRECTORY</param-name> <param-value>/WEB-INF/resources</param-value> </context-param>
在较老的JSF版本中,这是不可能的。
也可以看看:
- Java EE 6教程 – Facelets – 资源 (只有两章远离链接)
- 什么是JSF资源库,以及如何使用它?
- 如何用自定义样式覆盖默认的PrimeFaces CSS?
假设您正在运行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中; ,那么您需要删除前导斜杠,以便它与当前上下文(页面的一个)相关。 JSP):
<link rel="stylesheet" type="text/css" href="styles/decoration.css" />
这些答案帮助我解决了同样的问题。 虽然自从我使用SASS和GULP以来,我的问题变得更加复杂。
我不得不改变(请注意#前面的“\”。可能从吞咽的副作用:
<h:outputStylesheet library="my_theme" name="css/default.css"/> background: $blue url("\#{resource['my_themehttp://img.dovov.combackground-homepage-h1.png']}");