如何在使用JSF 2.0 Facelets时通过XHTML引入另一个XHTML?

235

如何在一个XHTML页面中正确地包含另一个XHTML页面?我已经尝试了不同的方法,但都没有成功。

2个回答

451

<ui:include>

最基本的方法是使用<ui:include>。被包含的内容必须放置在<ui:composition>中。

主页面/page.xhtml的启动示例:

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title>Include demo</title>
    </h:head>
    <h:body>
        <h1>Master page</h1>
        <p>Master page blah blah lorem ipsum</p>
        <ui:include src="/WEB-INF/include.xhtml" />
    </h:body>
</html>

包含页面/WEB-INF/include.xhtml(是的,这就是文件的全部内容,任何在<ui:composition>之外的标签都是不必要的,因为它们无论如何都会被Facelets忽略):

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h2>Include page</h2>
    <p>Include page blah blah lorem ipsum</p>
</ui:composition>
  

需要通过/page.xhtml打开此文件。请注意,您不需要在包含文件中重复使用<html><h:head><h:body> 标签,因为这样会导致无效的HTML

您可以在<ui:include src>中使用动态EL表达式。参见如何通过导航菜单进行ajax刷新动态包含内容?(JSF SPA).


<ui:define>/<ui:insert>

一种更高级的包含方式是“模板”。这基本上是另一种方式。主模板页面应使用<ui:insert> 声明插入已定义模板内容的位置。使用主模板页面的模板客户端页面应使用<ui:define> 定义要插入的模板内容。

主模板页面/WEB-INF/template.xhtml(作为设计提示:标题、菜单和页脚甚至可以是<ui:include>文件):

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title><ui:insert name="title">Default title</ui:insert></title>
    </h:head>
    <h:body>
        <div id="header">Header</div>
        <div id="menu">Menu</div>
        <div id="content"><ui:insert name="content">Default content</ui:insert></div>
        <div id="footer">Footer</div>
    </h:body>
</html>

模板客户端页面/ page.xhtml(请注意 template 属性;此处也是完整文件):

<ui:composition template="/WEB-INF/template.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets">

    <ui:define name="title">
        New page title here
    </ui:define>

    <ui:define name="content">
        <h1>New content here</h1>
        <p>Blah blah</p>
    </ui:define>
</ui:composition>

此页面需要用/page.xhtml打开。如果没有<ui:define>,则将显示<ui:insert>中的默认内容(如果有)。


<ui:param>

您可以使用<ui:param><ui:include><ui:composition template>传递参数。

<ui:include ...>
    <ui:param name="foo" value="#{bean.foo}" />
</ui:include>
<ui:composition template="...">
    <ui:param name="foo" value="#{bean.foo}" />
    ...
</ui:composition >

在include/template文件中,你可以使用#{foo}进行引用。如果需要向<ui:include>传递多个参数,则最好将include文件注册为标签文件,这样你最终可以像这样使用它:<my:tagname foo="#{bean.foo}">。参见When to use <ui:include>, tag files, composite components and/or custom components?

你甚至可以通过<ui:param>传递整个bean、方法和参数。参见JSF 2: how to pass an action including an argument to be invoked to a Facelets sub view (using ui:include and ui:param)?


设计提示

那些不希望通过URL直接访问的文件应该放置在/WEB-INF文件夹中,例如上面示例中包含文件和模板文件。参见Which XHTML files do I need to put in /WEB-INF and which not?

<ui:composition><ui:define>之外不需要任何标记(HTML代码)。你可以放置任何标记,但是它们将被Facelets 忽略。放置标记只对网页设计师有用。参见Is there a way to run a JSF page without building the whole project?

HTML5 doctype是目前推荐使用的doctype,尽管它是一个XHTML文件。你可以将XHTML视为一种语言,它允许你使用基于XML的工具生成HTML输出。参见Is it possible to use JSF+Facelets with HTML 4/5?JavaServer Faces 2.2 and HTML5 support, why is XHTML still being used

CSS/JS/image文件可以作为动态可重定位/本地化/版本化资源进行包含。参见How to reference CSS / JS / image resource in Facelets template?

你可以将Facelets文件放入可重用的JAR文件中。参见Structure for multiple JSF projects with shared code

有关高级Facelets模板的实际示例,请查看Java EE Kickoff App源代码的src/main/webapp文件夹和OmniFaces演示站点源代码


1
嗨,Balus,关于:最基本的方法是ui:include。包含的内容必须放在ui:composition中。我认为包含的内容可以简单地放在<p></p>中,它就会起作用。 - Koray Tugay
1
@KorayTugay:是的,没错。ui:composition 只有在 a) 使用模板(见上文),或 b) 将所有内容包装在 <html><body> 中以便在浏览器或 HTML 编辑器中加载文件时才必需。 - sleske
1
@Odysseus:如果它真的是一个组合,那就不一样了。 - BalusC
非常好的、精确的解释,它使用两种方法的比较来解释一切。 - M. Atif Riaz
1
据我所知,如果在facelet中只声明<ui:composition ...>,则必须像这样声明doctype:<!DOCTYPE html PUBLIC "-// W3C // DTD XHTML 1.0 Transitional // EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,否则使用HTML实体时会出现"entity referenced but not declared"错误。 - ChristophS
显示剩余4条评论

25

包含的页面:

<!-- opening and closing tags of included page -->
<ui:composition ...>
</ui:composition>

包含页面:

<!--the inclusion line in the including page with the content-->
<ui:include src="yourFile.xhtml"/>
  • 在上面所示的代码中,使用ui:composition开始您的包含xhtml文件。
  • 像上面展示的那样,在包含xhtml文件中使用ui:include引入该文件。

有时候仅仅使用文件名来识别路径是不够的。对于那些尝试过文件包含但失败了的人,你可以尝试在文件名前面添加斜杠符号或者/WEB-INF目录。这样看起来就像 <ui:include src="/yourFile.xhtml"/> 或者 <ui:include src="/WEB-INF/yourFile.xhtml"/> - Oleksa O.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接