JSF 2.0 Facelets 的模板技术

作者:Deepak Vohra

2011 年 8 月发布

下载:
下载Oracle WebLogic Server 11g 第 1 版 (10.3.4) 安装程序

下载Apache Jakarta Standard 1.1 Taglib

下载Facelets.zip

简介

在 JavaServer Faces (JSF) 2.0 中,Facelets 取代 JavaServer Pages (JSP) 成为默认的视图声明语言 (VDL)。有了 Facelets,您不需要像以前在 JSF 1.2 中那样配置视图处理器。Facelets 是一种以 JSF 为中心的视图技术。

Facelets 以组合为基础。一个组合定义一个 Facelets 页中的 JSF UIComponent 结构。Facelets 应用程序可以包含多个组合,这些组合在不同的 Facelets 页中定义、作为一个应用程序运行。

Facelets 是一种类似 Tiles 的模板化框架。与 Tiles 相比,Facelets 的优势在于它预先集成了 JSF UIComponent,并且不需要 Facelets 配置文件,而 Tiles 需要 Tiles 配置文件。

在 Facelets 中可以添加 JSF 验证器和转换器。Facelets 全面支持表达式语言 (EL) 和 JavaServer Pages Standard Tag Library (JSTL)。在 Web 应用程序中使用 Facelets 的部分好处包括模板化、重用和易于开发。

在本文中,我们将在 Oracle Enterprise Pack for Eclipse 11g 中开发一个 Facelets Web 应用程序,然后将该应用程序部署到 Oracle WebLogic Server 11g。在该 Facelets 应用程序中,将一个输入文本 UIComponent 添加到输入 Facelets 页。借助 JSF 导航,将该输入 Facelets 页导航到另一 Facelets 页,这个 Facelets 页显示由输入 Facelets 页指定的 SQL 查询生成的 JSF 数据表。我们将使用 Oracle Database 11g 快捷版作为数据源。通过在输入和输出的页眉和页脚中包含图形来展示模板功能;只需在模板中指定图形一次。

:本文中开发的 Facelets Web 应用程序的源代码可以从这里下载

Facelets 技术概述

在开发应用程序之前,我们先回顾一下 Facelets 技术。Facelets 标记与 JSF Core 和 JSF HTML 标记库结合使用,开发 JSF Facelets 应用程序。表 1 讨论了一些 Facelets 标记。

表 1. Facelets 标记

Facelets 标记

说明

属性

ui:composition

定义 UIComponent 组合。一个组合可以由多个 UIComponent 组成。Facelets 页中仅编译 ui:composition 标记内的文本。

template:可选属性,指定用于在组合内添加 UIComponent 的模板。

ui:define

用于在 Facelets 页中使用模板添加内容。

name:必需的属性;与 ui:insert 中的 name 属性相匹配。

ui:decorate

类似于 ui:composition,只不过 ui:decorate 标记中不包括的文本也会编译到 Facelets 页中。

template:必需的属性,指定 ui:decorate 标记中用于添加 UIComponent 的模板。

ui:component

类似于 ui:composition,只不过在 UIComponent 结构中添加一个新的 UIComponent 作为根组件。

id:如果未指定,则 Facelets 分配一个 ID。

binding:将 UIComponent 与 JavaBean 的一个属性绑定。

ui:fragment

ui:component 对应的非修整标记,类似于 ui:composition 对应的 ui:decorate 标记。

id:如果未指定,则 Facelets 分配一个 ID。

binding:将 UIComponent 与 JavaBean 的一个属性绑定。

ui:include

包括一个 Facelets 页,该页定义 Facelets 页或模板页中的一个组合或组件。

src:必需的属性,通过 EL 表达式或字符串文字指定要包括的目标 Facelets 页。

ui:insert

用于模板中为使用该模板定义 UIComponent 的 Facelets 页面定义布局。模板客户端使用相应的 ui:define 标记将 UIComponent 添加到 Facelets 页。如果一个 Facelets 页指定了一个模板但没有指定与 ui:insert 标记对应的 ui:define 标记,Facelets 页中将使用默认的 ui:insert 标记。

name:在 Facelets 页的 ui:define 标记中拥有相应 name 属性的属性,用于将模板与 Facelets 页匹配。

ui:param

当模板或 Facelets 页中包括一个 Facelets 页时指定一个变量。

name:必需的属性,指定变量名称。

value:必需的属性,指定变量值为 EL 表达式或文字。

默认情况下,Facelets 页为 XHTML 页。Facelets 应用程序由以下配置文件和模板文件组成。

  • 一个 Facelet 模板文件,这是一个 XHTML 页
  • Facelet 页眉和 Facelet 页脚 XHTML 页
  • 一个 JSF 配置文件 faces-config.xml
  • Facelet 组合页,也是一个 XHTML 页

模板文件定义 Facelets 中的布局,包含 <ui:insert/> 标记,用于指定使用模板定义 UIComponent 的 Facelets 组合的结构。

JSF 配置文件是唯一需要的配置文件;不需要 Facelets 配置文件。一个 Facelets 页是一个 XHTML 页,包括 Facelets 命名空间中定义的标记。

在下文中,我们将在 Oracle Enterprise Pack for Eclipse 11g、Oracle WebLogic Server 11g 和 Oracle Database 11g 快捷版中创建一个 Facelets 应用程序。

先决条件

必须具备以下先决条件:

搭建环境

首先,我们需要在 Oracle Database 快捷版中创建一个数据库表。

  1. 安装 Oracle Database 11g 快捷版。
  2. 使用以下 SQL 脚本创建用户 OE 和一个表。
CREATE USER OE IDENTIFIED BY OE;
 GRANT CONNECT, RESOURCE to OE;
CREATE TABLE OE.Catalog(CatalogId INTEGER 
   PRIMARY KEY, Journal VARCHAR(25), Publisher VARCHAR(25),
    Edition VARCHAR(25), Title Varchar(45), Author Varchar(25));
   INSERT INTO OE.Catalog VALUES('1', 'Oracle Magazine',  
    'Oracle Publishing', 'Nov-Dec 2004', 'Database Resource  
   Manager', 'Kimberly Floss');
   INSERT INTO OE.Catalog VALUES('2', 'Oracle Magazine',   
    'Oracle Publishing', 'Nov-Dec 2004', 'From ADF UIX to JSF',  
   'Jonas Jacobi');
   INSERT INTO OE.Catalog VALUES('3', 'Oracle Magazine',   
    'Oracle Publishing', 'March-April 2005', 'Starting with  
   Oracle ADF ', 'Steve Muench');
  1. 将 Standard 1.1 Taglib filesstandard.jar 和 jstl.jar 添加到 domain/bin/startWebLogic 批处理脚本中以设置 CLASSPATH 变量。
C:\JSTL\jakarta-taglibs-standard-1.1.2\lib\standard.jar;C:\JSTL\jakarta-taglibs-standard-1.1.2\lib\jstl.jar

在 Oracle WebLogic Server 中配置 JSF 2.0 支持

默认情况下,Oracle WebLogic Server 11g 中没有配置 JSF 2.0 支持。要配置 JSF 2.0 支持,请执行以下步骤:

  1. 启动 Oracle WebLogic Server 及其 Administration Console。
  2. 在 wls_base_domain 节点中选择 Deployments 节点。
  3. 在 Deployment 表中,单击 Install 按钮。

    facelet 1
  4. 选择 jsf-2.02.war 并单击 Next

    facelet 2
  5. 在 Choose 目标样式中,选择 Install this deployment as a library。单击 Next
  6. 选择默认的 Optional Settings,然后单击 Next
  7. 单击 Finish 完成 JSF 2.0 部署。
  8. 在配置屏幕,单击 Save 保存配置。


在 Deployments 中添加了一个 JSF 2.0 部署配置。
facelet 4

在配置文件 C:\Oracle\Middleware\user_projects\domains\wls_base_domain\config\config.xml 中配置了 JSF 2.0 库。

<library>
       <name>jsf#2.0@1.0.0.0_2-0-2</name>
       <target>AdminServer</target>
       <module-type>war</module-type>
       <source-path>C:\Oracle\Middleware\wlserver_10.3\common\deployable-libraries\jsf-2.0.2.war</source-path>
       <deployment-order>100</deployment-order>
       <security-dd-model>DDOnly</security-dd-model>
</library>

在 Oracle Enterprise Pack for Eclipse 中创建一个 Facelets 项目


执行以下步骤创建一个 Facelets 项目:

  1. 在 Oracle Enterprise Pack for Eclipse 11g 中通过 File>New>Dynamic Web Project 创建一个项目。
  2. 在 Dynamic Web Project Configuration 中,指定项目名称(如 Facelets)并使用 New Runtime 创建一个新的目标运行时。
  3. 在 New Server Runtime Environment Configuration 中,选择 Oracle WebLogic Server 11g R1 PatchSet 3,选择 Create a new local server,然后单击 Next
  4. 指定 Oracle WebLogic Server 主目录。Java 主目录配置为 JDK 1.6。单击 Next
  5. 对于服务器配置,选择 Local 作为 Server Type,然后选择 wls_base_domain 目录作为 Domain Directory。单击 Finish
  6. 选择 2.5 作为 Dynamic web module version。
  7. 对于 Facelets 支持,我们需要添加 JSF 2.0 配置。单击 Configuration 部分的 Modify 按钮。
  8. 在 Project Facets 中,选择 JavaServer Faces,然后对 Version 选择 2.0。单击 OK

    facelet 5
  9. 确保将 Configuration 设置为 <custom>,如下图所示。单击 Next

    facelet 6
  10. 对于 Java 配置,默认的输出文件夹设置为 build/classes。单击 Next
  11. 对于 Web Module 配置,选择 Facelets 作为 Context root,选择 WebContent 作为 Content directory。选择 Generate web.xml deployment descriptor,然后单击 Next
  12. 要配置 JSF 实现库,选择 User Library 作为 Type,然后单击 Download 按钮。
  13. 对于 Download Library,选择 JSF 2.0 (Mojarra 2.0.3-FCS) 库,然后单击 Next

    facelet 7
  14. 接受库许可并单击 Finish。JSF 实现库配置完成。
  15. 单击 Finish

    facelet 8

    Facelets 项目创建完毕。

    facelet 9
  16. 在 JSF 2.0 中,不需要 javax.faces.VIEW_MAPPINGS context-param,Facelets 页的默认后缀为 .xhtml。将以下 context-param 添加到 web.xml。
  17.      
         <context-param>
                     <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                     <param-value>.xhtml</param-value>
         </context-param>
       

    当选择 JSF 项目 facet 时,会默认配置 Faces Servlet。下图显示了 web.xml 文件:

    facelet 10


  18. 将 JSF 2.0 库的库配置添加到 weblogic.xml。
<wls:library-ref>
               <wls:library-name>jsf</wls:library-name>
               <wls:specification-version>2.0</wls:specification-version>
               <wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version>
               <wls:exact-match>true</wls:exact-match>
</wls:library-ref> 

创建托管 Bean

执行以下步骤创建一个托管 bean:

  1. 要为 Facelets 应用程序创建一个托管 bean,右键单击
    WebContent/WEB-INF/faces-config.xml 并选择 Open With>Faces Config Editor

  2. facelet 11

  3. 单击 Add 添加托管 bean。

  4. facelet 12

  5. 在 New Managed Bean 向导中,选择 Create a new Java class 并单击 Next
  6. 为 Source 文件夹选择 Facelets/src,为 Package 选择 catalog.backing,为 Catalog 选择 Java 类名。单击 Next
  7. 输入 catalog 作为托管 bean 的名称,为 Scope 选择 session。然后单击 Next
  8. 单击 Finish。于是添加了一个托管 bean。

facelet 13

 

创建 Facelets 模板

执行以下步骤创建一个 Facelets 模板:

  1. 首先,在 WEB-INF 目录中创建 templates 目录。
  2. 接下来,将用于 Facelets 模板文件的 XHTML 页添加到 templates 目录。
  3. 右键单击 WebContent 文件夹,然后选择 New>XHTML Page

  4. facelet 14

  5. 在 New XHTML File 向导中,将 File 名称域设为 BasicTemplate,然后单击 Next

  6. facelet 15

  7. 选择 New Facelet Template 并单击 Finish


  8. facelet 16

    包含页眉、内容和页脚的 BasicTemplate.xhtml 添加到了 templates 目录。

    facelets 17

    模板的根元素是 html,包括针对 Facelets 命名空间的命名空间声明。

  9. 在模板中,为 Facelets 组合的不同部分添加包含在 <div/> 标记中的 ui:insert 标记:标题、页眉、内容部分以及页脚。
  10. 使用 ui:include 标记指定 header.xhtmlfooter.xhtml Facelets 页的相对路径。下面列出了 BasicTemplate.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<title><ui:insert name="title">JSF Facelets</ui:insert></title>
</head>
<body>
<div id="header">
        <ui:insert name="header">
           <ui:include src="/WEB-INF/templates/header.xhtml" />
        </ui:insert>
</div>
<div id="content">
       <ui:insert name="content">
      <!--  include your content file or uncomment the include below and create content.xhtml in this directory -->
         <!-- <div> -->
         <!-- <ui:include src="content.xhtml"/> -->
         <!-- </div> -->
       </ui:insert>
</div>
<div id="footer">
      <ui:insert name="footer">
         <ui:include src="/WEB-INF/templates/footer.xhtml" />
      </ui:insert>
</div>
</body>
</html> 

创建 Facelets 页

执行以下步骤创建 Facelets 页:

  1. 类似于 BasicTemplate.xhtml 的创建步骤,为 header.xhtml 和 footer.xhtml 以及输入 Facelets 页 (input.xhtml) 和输出 Facelets 页 (output.xhtml) 分别添加 XHTML 页。
  2. 对于 header.xhtml,选择 New Facelet Header 模板。
  3. 对于 footer.xhtml,选择 New Facelet Footer 模板。
  4. 对于 input.xhtml 和 output.xhtml,选择 New Facelet Composition Page 模板。
  5. 将 Facelet 组合页添加到 WebContent 目录。

  6. Facelets 应用程序中显示出基于不同类型模板的 XHTML 页。


    facelet 18

  7. 在 header.xhtml 页中,使用 h:graphicImage 标记为页眉指定一个 .jpg 文件。下面列出了 header.xhtml 页。
  8.    
       <?xml version="1.0" encoding="ISO-8859-1" ?>
       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
       <html xmlns="http://www.w3.org/1999/xhtml"
           xmlns:ui="http://java.sun.com/jsf/facelets"
           xmlns:h="http://java.sun.com/jsf/html"
           xmlns:f="http://java.sun.com/jsf/core">
       <f:view>
       <h:form>
                   <h:panelGrid columns="1">
                         <h:graphicImage value="FaceletsHeader.jpg" />
                   </h:panelGrid>
             </h:form>
       </f:view>
       </html>   
    
    
  9. footer.xhtml 页,使用包含在 h:panelGrid 标记中的 h:graphicImage 标记为页脚指定一个 .jpg 文件。下面列出了 footer.xhtml 页。
  10.    
       <?xml version="1.0" encoding="ISO-8859-1" ?>
       <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
       <html xmlns="http://www.w3.org/1999/xhtml"
           xmlns:ui="http://java.sun.com/jsf/facelets"
           xmlns:h="http://java.sun.com/jsf/html"
           xmlns:f="http://java.sun.com/jsf/core">   
       <f:view>
       <h:form>
                   <h:panelGrid columns="1">
                         <h:graphicImage value="FaceletsFooter.jpg" />
                   </h:panelGrid>
             </h:form>
       </f:view>
       </html>   
  11. 将页眉和页脚 .jpg 文件复制到 WebContent 目录,也就是组合页 input.xhtml 和 output.xhtml 所使用的目录。

  12. :源代码 {PRODUCTION:在此插入到 Facelets.zip 的链接。} 文件中包括了示例 FaceletsHeader.jpg 和 FaceletsFooter.jpg 文件,不过您可以使用任何 .jpg 文件。

  13. 接下来,定义 input.xhtml Facelet 组合页,该页在内容部分有一个用于输入文本的输入域(h:inputText 组件)和一个用于提交输入的 h:commandButton。

h:commandButton 将其绑定指定为托管 bean catalog 中的 commandButton1 组件。在托管 bean 中,该命令按钮的 action 属性设置为 catalog.commandButton1_action 方法。

Facelets 页 input.xhtml 中包含一个 ui:composition 标记,用于定义 Facelets 页的组合,ui:composition 标记中的 ui:define 标记用于定义 Facelets 组合、页眉、内容和页脚的不同部分的 UIComponent。

在 ui:composition 标记的 template 属性中指定模板名称。ui:define 标记对应于模板中的 ui:insert 标记。如果没有为相应的 ui:insert 标记指定 ui:define 标记,则在 Facelet 组合页中使用 BasicTemplate.xhtml 页中默认的 ui:insert 标记。在 input.xhtml 页中只定义了内容的 ui:define 标记;页眉和页脚部分使用的是在 header.xhtml 和 footer.xhtml 中指定并且通过 ui:insert 和 ui:include 包括在 BasicTemplate.xhtml 中的页眉和页脚 .jpg 文件。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
       <ui:define name="content">
<h:form>
               <h:panelGrid columns="2">
                     <h:outputLabel binding="#{catalog.outputLabel1}" value="SQL Query:" />
                     <h:inputText binding="#{catalog.inputText1}" />
                     <h:commandButton value="Submit" binding="#{catalog.commandButton1}"
                     action="#{catalog.commandButton1_action}" />
               </h:panelGrid>
         </h:form>
       </ui:define>
</ui:composition>
</html>

output.xhtml Facelets 组合页的内容部分包含一个 h:dataTable UI 组件,用于输出 input.xhtml Facelet Composition 页中 SQL 查询到的 JSF 数据表。内容的 ui:define 标记定义 Facelets 页的组合。h:dataTable 绑定到托管 bean 中的 dataTable1 属性,h:column 组件分别绑定到托管 bean 中的 column1、olumn2…column6 属性。下面列出了 Facelet 组合页的 output.xhtml 文件。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
       <ui:define name="content">
           <h:form>
               <h:dataTable  binding="#{catalog.dataTable1}" border="1" rows="5">
                     <h:column binding="#{catalog.column1}"></h:column>
                     <h:column binding="#{catalog.column2}"></h:column>
                     <h:column binding="#{catalog.column3}"></h:column>
                     <h:column binding="#{catalog.column4}"></h:column>
                     <h:column binding="#{catalog.column5}"></h:column>
                     <h:column binding="#{catalog.column6}"></h:column>
               </h:dataTable>
         </h:form>
       </ui:define>
</ui:composition>
</html>

 

为 Facelets 应用程序指定导航

下面我们在 faces-config.xml 中添加导航规则,以便在 Facelets 应用程序中添加导航功能。

  1. 添加 Facelet 组合页 error.xhtml 以便在出现错误时进行导航。
  2. 打开 faces-config.xml,选择 Navigation Rule 选项卡。
  3. 将 input.xhtml 和 output.xhtml Facelet 组合页以及 error.xhtml 页拖到 Navigation Rule 中。
  4. 要在两个 Facelets 页之间创建导航规则,如在 input.xhtml 和 output.xhtml 之间,选择组件模板中的 Link。           

    facelet 19

  5. 要在两个 Facelets 页之间添加导航实例,使用组件模板中的 Select 选择一个链接。

    facelet 20
  6. 要定义链接属性,右键单击一个链接并选择 Show View>Properties

    facelet 21
  7. Link>From Outcome 域中指定所需的导航。为从 input.xhtml 到 output.xhtml 的链接指定“success”,这样,如果来自 input.xhtml 的输出结果是“success”,则导航到 output.xhtml。为从 input.xhtml 到 error.xhtml 的链接指定“failure”,这样,如果结果是“failure”,则导航到 error.xhtml。

    facelet 22

    下面列出了包含托管 bean 和导航规则的 faces-config.xml 配置文件。
    <?xml version="1.0" encoding="UTF-8"?>

    <faces-config
           xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
           version="2.0">
             <application>
                   <message-bundle>resources.application</message-bundle>
                   <locale-config>
                         <default-locale>en</default-locale>
                   </locale-config>
             </application>
             <managed-bean>
                   <managed-bean-name>catalog</managed-bean-name>
                   <managed-bean-class>catalog.backing.Catalog</managed-bean-class>
                   <managed-bean-scope>session</managed-bean-scope>
             </managed-bean>
             <navigation-rule>
                   <display-name>input.xhtml</display-name>
                   <from-view-id>/input.xhtml</from-view-id>
                   <navigation-case>
                         <from-outcome>success</from-outcome>
                         <to-view-id>/output.xhtml</to-view-id>
                   </navigation-case>
             </navigation-rule>
             <navigation-rule>
                   <display-name>input.xhtml</display-name>
                   <from-view-id>/input.xhtml</from-view-id>
                   <navigation-case>
                         <from-outcome>failure</from-outcome>
                         <to-view-id>/error.xhtml</to-view-id>
                   </navigation-case>
             </navigation-rule>
    </faces-config> 
    
    
  8. Catalog.java 中,即托管 bean 的 Java 类,为 HTML 和 UI 组件添加所需的导入语句。为数据表添加一个 HtmlDataTable 变量,为数据表列添加一些 UIColumn 组件变量。另外,为表单添加一些 HTML 组件变量,输入文本以指定一个 SQL 查询,添加一个用于提交 SQL 查询的命令按钮

    我们在构建 XHTML 页时,将 HTML 和 UI 组件变量绑定到了 Facelets 组合 XHTML 页的 JSF 组件。

  9. private HtmlDataTable dataTable1;
             private UIColumn column1;
             private UIColumn column2;
             private UIColumn column3;
             private UIColumn column4;
             private UIColumn column5;
             private UIColumn column6; 
        
  10. 为 HTML 和 UI 组件添加访问器方法。添加一个在单击 Submit 按钮时调用的方法。
    public String commandButton1_action() { }
  11. 在 Submit 按钮 action 方法中,检索 JSF 输入文本域中的 SQL 查询输入并运行 SQL 查询以生成结果集。
    rs = stmt.executeQuery((String) inputText1.getValue());
  12. 设置数据表的边界和单元格填充形式。还要设置代表数据表中一行数据的变量。
    dataTable1.setBorder(5);
       dataTable1.setCellpadding("1");
       dataTable1.setVar("catalog");
  13. 设置数据表中各列的标题值。数据表中各列与数据库表中的各列相对应。

    通过创建 HtmlOutputText 标题组件并利用 setHeader 方法在 UIColumn 组件上设置标题来添加列标题。使用 setValue 方法设置 HtmlOutputText 值。例如,下面的代码添加 CatalogId 列的列标题:
       HtmlOutputText headerComponent = new HtmlOutputText();
       headerComponent.setValue("CatalogId");
       column1.setHeader(headerComponent); 
  14. 为数据表中的每列创建一个 HtmlOutputText 组件,为 HtmlOutputText 组件指定一个值表达式,并将组件添加到列中。

    这就创建了一个 ValueExpression 对象,具体创建过程:首先创建一个 FacesContext 对象,然后从 FacesContext 创建一个 ELContext 对象和一个 ExpressionFactory 对象,最后从 ExpressionFactory 对象和 ELContext 对象创建一个 ValueExpression 对象。使用 setValueExpression 方法设置 HtmlOutputText 组件的值表达式。
    通过调用 getChildren 方法然后调用 add 方法,将 HtmlOutputText 组件添加到 UIColumn 组件。例如,为 CatalogId 列添加了 HtmlOutputText 组件,如下所示。
    HtmlOutputText column1Text = new HtmlOutputText();
       FacesContext fCtx = FacesContext.getCurrentInstance();
       ELContext elCtx = fCtx.getELContext();
       ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
       ValueExpression ve = ef.createValueExpression(elCtx,
                                     "#{catalog.catalogid}", String.class);
       column1Text.setValueExpression("value", ve);
       column1.getChildren().add(column1Text); 
  15. 创建一个 ResultSetDataModel 对象。使用 ResultSetDatModel 对象来封装 ResultSet 对象,ResultSet 对象必须可以滚动。用 setWrappedData 方法将由 SQL 查询检索到的 ResultSet 设置为用于 ResultSetDataModel 的数据。
    ResultSetDataModel dataModel=new ResultSetDataModel();
       dataModel.setWrappedData(rs); 
  16. 使用 setValue 方法将数据表与 ResultSetDataModel 对象绑定。
dataTable1.setValue(dataModel);

下面列出了托管 bean Java 类 Catalog.java。

package catalog.backing;
import javax.faces.component.html.HtmlCommandButton;
   import javax.faces.component.html.HtmlDataTable;
   import javax.faces.component.html.HtmlForm;
   import javax.faces.component.html.HtmlInputText;
   import javax.faces.component.html.HtmlOutputLabel;
   import javax.faces.component.UIColumn;
   import javax.faces.component.html.HtmlOutputText;
   import javax.faces.context.FacesContext;
   import javax.el.*;
   import javax.faces.model.ResultSetDataModel;
   import java.sql.*;
public class Catalog {
         private HtmlForm form1;
         private HtmlInputText inputText1;
         private HtmlOutputLabel outputLabel1;
         private HtmlCommandButton commandButton1;
         private HtmlDataTable dataTable1;
         private UIColumn column1;
         private UIColumn column2;
         private UIColumn column3;
         private UIColumn column4;
         private UIColumn column5;
         private UIColumn column6;
         private Statement stmt;
         private Connection connection;
         private ResultSet rs;
      public void setForm1(HtmlForm form1) {
               this.form1 = form1;
         }
      public HtmlForm getForm1() {
               return form1;
         }
      public void setInputText1(HtmlInputText inputText1) {
               this.inputText1 = inputText1;
         }
      public HtmlInputText getInputText1() {
               return inputText1;
         }
      public void setOutputLabel1(HtmlOutputLabel outputLabel1) {
               this.outputLabel1 = outputLabel1;
         }
      public HtmlOutputLabel getOutputLabel1() {
               return outputLabel1;
         }
      public void setCommandButton1(HtmlCommandButton commandButton1) {
               this.commandButton1 = commandButton1;
         }
      public HtmlCommandButton getCommandButton1() {
               return commandButton1;
         }
      public void setDataTable1(HtmlDataTable dataTable1) {
               this.dataTable1 = dataTable1;
         }
      public HtmlDataTable getDataTable1() {
               return dataTable1;
         }
      public void setColumn1(UIColumn column1) {
               this.column1 = column1;
         }
      public UIColumn getColumn1() {
               return column1;
         }
      public void setColumn2(UIColumn column2) {
               this.column2 = column2;
         }
      public UIColumn getColumn2() {
               return column2;
         }
      public void setColumn3(UIColumn column3) {
               this.column3 = column3;
         }
      public UIColumn getColumn3() {
               return column3;
         }
      public void setColumn4(UIColumn column4) {
               this.column4 = column4;
         }
      public UIColumn getColumn4() {
               return column4;
         }
      public void setColumn5(UIColumn column5) {
               this.column5 = column5;
         }
      public UIColumn getColumn5() {
               return column5;
         }
      public void setColumn6(UIColumn column6) {
               this.column6 = column6;
         }
      public UIColumn getColumn6() {
               return column6;
         }
      public String commandButton1_action() {
               // Add event code here...
            try {
                  Class.forName("oracle.jdbc.OracleDriver");
                  String url = "jdbc:oracle:thin:@localhost:1521:XE";
                  connection = DriverManager.getConnection(url, "OE", "OE");
                  stmt = connection.createStatement(
                                 ResultSet.TYPE_SCROLL_INSENSITIVE,
                                 ResultSet.CONCUR_READ_ONLY);
                  rs = stmt.executeQuery((String) inputText1.getValue());
                  HtmlDataTable dataTable1 = new HtmlDataTable();
                     dataTable1.setBorder(5);
                     dataTable1.setCellpadding("1");
                     dataTable1.setVar("journalcatalog");
                     ResultSetDataModel dataModel = new ResultSetDataModel();
                  dataModel.setWrappedData(rs);
                  this.setDataTable1(dataTable1);
                  UIColumn column1 = new UIColumn();
                     UIColumn column2 = new UIColumn();
                     UIColumn column3 = new UIColumn();
                     UIColumn column4 = new UIColumn();
                     UIColumn column5 = new UIColumn();
                     UIColumn column6 = new UIColumn();
                  this.setColumn1(column1);
                     this.setColumn2(column2);
                     this.setColumn3(column3);
                     this.setColumn4(column4);
                     this.setColumn5(column5);
                     this.setColumn6(column6);
                  HtmlOutputText headerComponent = new HtmlOutputText();
                     headerComponent.setValue("CatalogId");
                     column1.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Journal");
                     column2.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Publisher");
                     column3.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Edition");
                     column4.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Title");
                     column5.setHeader(headerComponent);
                     headerComponent = new HtmlOutputText();
                     headerComponent.setValue("Author");
                     column6.setHeader(headerComponent);
                  HtmlOutputText column1Text = new HtmlOutputText();
                  FacesContext fCtx = FacesContext.getCurrentInstance();
                     ELContext elCtx = fCtx.getELContext();
                     ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
                     ValueExpression ve = ef.createValueExpression(elCtx,
                                 "#{journalcatalog.catalogid}", String.class);
                  column1Text.setValueExpression("value", ve);
                  column1.getChildren().add(column1Text);
                  HtmlOutputText column2Text = new HtmlOutputText();
                  fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.journal}",
                                 String.class);
                     column2Text.setValueExpression("value", ve);
                  column2.getChildren().add(column2Text);
                     HtmlOutputText column3Text = new HtmlOutputText();
                  fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.publisher}",
                                 String.class);
                     column3Text.setValueExpression("value", ve);
                  column3.getChildren().add(column3Text);
                     HtmlOutputText column4Text = new HtmlOutputText();
                     fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.edition}",
                                 String.class);
                     column4Text.setValueExpression("value", ve);
                  column4.getChildren().add(column4Text);
                     HtmlOutputText column5Text = new HtmlOutputText();
                     fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.title}",
                                 String.class);
                     column5Text.setValueExpression("value", ve);
                  column5.getChildren().add(column5Text);
                     HtmlOutputText column6Text = new HtmlOutputText();
                     fCtx = FacesContext.getCurrentInstance();
                     elCtx = fCtx.getELContext();
                     ef = fCtx.getApplication().getExpressionFactory();
                     ve = ef.createValueExpression(elCtx, "#{journalcatalog.author}",
                                 String.class);
                     column6Text.setValueExpression("value", ve);
                  column6.getChildren().add(column6Text);
                  dataTable1.setValue(dataModel);
            } catch (SQLException e) {
                     System.out.println(e.getMessage());
                     return "failure";
            } catch (ClassNotFoundException e) {
                     System.out.println(e.getMessage());
                     return "failure";
               } finally {
            }
               return "success";
         }
   }

运行 Facelets 应用程序

接下来,在运行应用程序之前,我们需要为 Facelets 应用程序指定一些 factory 类。

  1. 添加 WEB-INF/classes/META-INF/services 目录。
  2. 在 services 目录中,利用在 factory 文件中指定的相应 factory 实现类创建以下 factory 文件。
  • 文件名:javax.faces.application.ApplicationFactory

类名:com.sun.faces.application.ApplicationFactoryImpl

  • 文件名:javax.faces.context.FacesContextFactory

类名:com.sun.faces.context.FacesContextFactoryImpl

  • 文件名:javax.faces.lifecycle.LifecycleFactory

类名:com.sun.faces.lifecycle.LifecycleFactoryImpl

  • 文件名:javax.faces.render.RenderKitFactory

类名:com.sun.faces.renderkit.RenderKitFactoryImpl

下图显示了 Facelets 应用程序的目录结构。

facelet 23

  1. 如果 Oracle WebLogic Server 没有运行,请启动它。
  2. 要运行 Facelets 应用程序,右键单击 input.xhtml 并选择 Run As>Run on Server

facelet 24

  1. 选择运行该应用程序的服务器。
  2. 单击 Next
  3. 选择默认设置并单击 Next
  4. 单击 Finish

创建一个 EAR 应用程序并将其部署到 Oracle WebLogic Server。

facelet 25

  1. 在 Oracle WebLogic Server 上,运行我们早前利用 URL http://localhost:7001/Facelets/faces/input.xhtml 为 JSF 2.0 配置的 input.xhtml Facelet 组合页。

输入 Facelets 页的三个部分分别为页眉、内容和页脚。Facelet 组合页的不同部分对应 input.xhtml Facelet 组合页的不同 ui:define 标记。来自 BasicTemplate.xhtml 模板的 header.xhtml 和 footer.xhtml 文件包含在组合中。

  1. 指定 SQL 查询 SELECT * FROM OE.CATALOG,单击 Submit

facelet 26

显示 output.xhtml Facelet 组合页,其中包括 SQL 查询生成的 JSF 数据表。

组合页中包含相同的 header.xhtmlfooter.xhtml,这展示了模板功能。显示相同的页眉和页脚 .jpg 文件。

facelet 27

另请参见

关于作者

Deepak Vohra 是一名 Sun 认证的程序员、Sun 认证的 Web 组件开发人员以及 Oracle 认证的初级人员。