|
开发人员:J2EE
在 JDeveloper 中利用 JSF 组件构建 Tiles 应用程序 作者:Deepak Vohra
了解如何在 Oracle JDeveloper 10g 中构建包含几个 JSF 组件页面的 Tiles 应用程序。
2005 年 12 月发表
Apache Struts Tiles 是一个 Struts 子项目,它支持基于模板创建 Web UI。 Tiles Document Assembly Framework 能够组装以 JSP、HTML 或 JavaServer Faces (JSF) 编写的表示页面(或 "tile")。 与 <jsp:include>/> 语法相比,Tiles 拥有一些优势。 因为每一个 tile 都可以重用,因此需要维护的 JSP/JSF 页面的数量将大大减少。
除了减少要维护的标记的数量之外,使用 Tiles 还有助于避免:
- JSP 元素的重复
- 每一次当指定的 JSP 发生变化时需要修改其他页面中 的引用
- 每一次当指定的 JSP 发生变化时需要修改布局
它的工作过程大致为: 在 Tiles 框架中,一个通用的 tile 定义页面将指定 tile 页面。 一个通用的布局页面(也被称为“模板”)指定在 tile 定义页面中定义的 tile 的布局。 因此,页面布局定义将指定 UI 应用程序中的 tile 的布局,而 tile 定义页面将指定 tile。 +因此对组件 tile 和模板的修改将被应用到所有使用那些 tile 和模板的页面上,从而支持显示页面的动态开发和布局设计。
在本教程中,您将了解到如何在 Oracle JDeveloper 10g(10.1.3;在撰写本文时发布了 EA1 版本)中开发包含几个 JSF 组件页面的 Tiles 应用程序: 标题页面、包含一个从 Oracle 数据库中生成的数据表的页面(该数据表也可以从一个返回结果集的 managed bean 中生成)和一个页脚页面。
概述
基于 Tiles 框架的表示 UI 页面由多个 tile 组成。 Tiles 应用程序包含
- 一个 tile 定义 XML 配置文件
- 一个布局页面
- Tile 页面
- 一个 JSP 包装页面
tile 定义页面定义了不同的 tile 和 tile 的 JSF/JSP 组件页面。 一些 tile 页面定义可能在 JSP 包装页面中定义。 布局页面指定 tile 页面 (tile) 的布局 — 一个可以应用到不同的显示页面上的模板。 tile 页面是组件 JSF 页面。 JSP 包装包含了用作 Tiles UI 页面定义和其他的 tile 定义的布局定义,它将被调用来运行 Tiles 框架应用程序。
准备安装
Struts 包含了 Tiles 框架。 Struts JAR 文件位于 JDeveloper 10.1.3 jakarta-struts 目录中。
- 下载并安装 JDeveloper 10g (10.1.3)。
- 下载并安装 Oracle 数据库 10g。
- 创建一个数据库实例。
- 创建一个数据库表 (OE.Catalog),并使用以下 SQL 脚本从中为 JSF 组件页面创建一个数据表。
CREATE TABLE OE.Catalog(ID VARCHAR(25)
PRIMARY KEY, Journal VARCHAR(25), Publisher VARCHAR(25),
Edition VARCHAR(25), Title Varchar(45), Author Varchar(25));
INSERT INTO OE.Catalog VALUES('catalog1', 'Oracle Magazine',
'Oracle Publishing', 'Nov-Dec 2004', 'Database Resource Manager
', 'Kimberly Floss');
INSERT INTO OE.Catalog VALUES('catalog2', 'Oracle Magazine', 'Oracle Publishing', 'Nov-Dec 2004',
'From ADF UIX to JSF', 'Jonas Jacobi');
INSERT INTO OE.Catalog VALUES('catalog3', 'Oracle Magazine', 'Oracle Publishing', 'March-April 2005',
'Starting with Oracle ADF ', 'Steve Muench');
在 JSF 应用程序中增加 Tiles 支持
首先,在 JDeveloper 中创建一个应用程序和一个工程。
 图 1 Tiles 工程
通过 File>New>Web Tier>JSF>JSF JSP 将一个 JSF JSP 页面(一个 tile)添加到 JSF/Tiles 工程中
 图 2 JSF JSP 页面
在 Web Application 框架中,选择 web application version 2.3 并单击 Next 按钮。 在 JSP File 框架中,指定文件名 catalog.jsp 并单击 Next 按钮。
在 Component Binding 框架中,选择 Automatically Bind Components Using a Newly Created Managed Bean 单选钮并单击 Next 按钮。
 图 3 组件绑定
在 Error Page Options 页面中,选择默认设置。
在 Tag Libraries 框架中,JSF HTML 和 JSF Core 标记库已被预先选定。单击 Next。 在 HTML Options 框架中,选择默认设置,并单击 Next。 在 Finish 框架中,单击 Finish。 一个 JSF JSP 页面 (catalog.jsp) 和 faces-config.xml 配置文件以及 JSF 页面的 Backing MBean 将被添加到工程中。
 图 4 catalog.jsp
将 JSF/Tiles 应用程序的 jar 文件添加到工程的 Web-inf/lib 目录中。 JSF/Tiles 工程需要以下 JAR 文件:
| JAR 文件 |
说明 |
| <JDeveloper10.1.3>/jsf-ri/jsf-impl.jar |
JSF RI 实现类 |
| <JDeveloper10.1.3>/jsf-ri/jsf-api.jar |
JSF API 类 |
| <JDeveloper10.1.3>/jakarta-struts/lib/struts.jar |
Tiles 框架类 |
| <JDeveloper10.1.3>/jakarta-taglibs/jstl-1.0/lib/standard.jar |
JSTL 标记类和 JSF RI 类 |
| <JDeveloper10.1.3>/jakarta-taglibs/jstl-1.1/lib/jstl.jar |
JSTL 标记的标记库类。 也和 JSF RI 类一起被引用 |
| <JDeveloper10.1.3>/jakarta-struts/lib/commons-beanutils.jar |
Java Beans 实用工具类 |
| <JDeveloper10.1.3>/jakarta-struts/lib/commons-digester.jar |
处理 XML 文档的类 |
| <JDeveloper10.1.3>/jakarta-struts/lib/commons-collections.jar |
J2SDK 集合框架扩展类 |
| <JDeveloper10.1.3>/jakarta-struts/lib/commons-logging.jar |
日志类 |
<JDeveloper10.1.3> 是安装 JDeveloper 10.1.3 的目录。
接下来,将 Tiles/JSF 框架 Jar 文件添加到工程类路径中。 在 Project Properties 框架中,选择 Add Library 按钮来添加一个新的资料库。
 图 5 添加资料库
添加对数据库进行 JDBC 访问所需的 Oracle JDBC 资料库,以检索示例数据库表。
 图 6 Oracle JDBC 资料库
添加 Struts.jar 文件,该文件包含了 Tiles 框架类。 除 Tiles 资料库和 JDBC 资料库之外,再添加在上表中列出的 jar 文件的资料库。
 图 7 Tiles 框架资料库
在 WEB-INF/web.xml 部署描述符中,指定一个上下文参数 (javax.faces.STATE_SAVING_METHOD),以保存 JSF 组件的状态。
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
参数值默认被设为 server(组件状态被存储在服务器中)。
在 web.xml 中,指定上下文初始参数 javax.faces.application.CONFIG_FILES。 将参数值设为 web 应用程序配置文件的路径。
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml, /WEB-INF/tiles-defs.xml</param-value>
</context-param>
通过在 web.xml 部署描述符中指定 Tiles Servlet 来添加对 Tiles 框架的支持。 将 definitions-config 初始参数值设为 tiles-defs.xml 配置文件的路径。
<servlet>
<servlet-name>Tiles Servlet</servlet-name>
<servlet-class>
org.apache.struts.tiles.TilesServlet
</servlet-class>
<init-param>
<param-name>definitions-config</param-name>
<param-value>/WEB-INF/tiles-defs.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
将 <JDeveloper 10.1.3>\jakarta-struts\lib\struts-tiles.tld 复制到 WEB-INF 目录中。 tiles-defs.xml 定义文件中的 Tiles 标记、布局页面和包装 JSP 都在 struts-tiles.tld 文件中定义,并且都位于 http://jakarta.apache.org/struts/tags-tiles 名字空间中。
开发 JSF/Tiles 应用程序
正如我之前说明的那样,该应用程序包含了 tiles header.jsp、catalog.jsp 和 footer.jsp JSF JSP 页面。 header.jsp JSF 页面包含了在 tile 应用程序顶端显示的 JPEG 图像。 catalog.jsp JSF 页面将显示一个从数据库表中生成的 JSF Data Table。 footer.jsp JSF 页面包含 tile 应用程序的页脚。 这些 tile 被组装在一个布局页面中。
接下来,为 Tiles 应用程序创建 tile。 (catalog.jsp tile 已在前一部分中创建了。) 在应用程序导航器中选择 catalog.jsp JSF 页面。 在组件选项板中选择 JSF HTML。 从组件选项板中将一个输入文本域和一个命令按钮添加到 JSF 页面中。 在属性检查器中将命令按钮的文本设为 Data Table。
接下来,从组件选项板中将一个 Data Table 添加到 JSF 页面中。
 图 8 添加数据表
Data Table Wizard 将启动。 在 Binding 框架中,选择 Number of Columns 单选钮,并在该域中将值指定为 6(对应数据库表中的列)。 单击 Finish 按钮。
这将在示例 Tiles 应用程序的 catalog.jsp tile 中创建一个数据表。 在输入文本域中指定一条 SQL 查询语句,并利用 Data Table 按钮生成一个数据表。 双击 Data Table 按钮。 在 commandButton_action 方法(如下所示)中利用 JSF API 从一条 SQL 查询中生成一个数据表。
public String commandButton_action()
{
// Add event code here...
ResultSet rs=null;
try {
Class.forName("oracle.jdbc.OracleDriver");
String url="jdbc:oracle:thin:@<host>:<port>:<database>";
Connection connection = DriverManager.getConnection(url,
"OE", "<password>");
Statement stmt=connection.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
rs=stmt.executeQuery((String)inputText1.getValue());
dataTable1.setBorder(5);
dataTable1.setCellpadding("1");
dataTable1.setVar("catalog");
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();
ValueBinding vb =
FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.id}");
column1Text.setValueBinding("value", vb);
column1.getChildren().add(column1Text);
HtmlOutputText column2Text=new HtmlOutputText();
vb =
FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.journal}");
column2Text.setValueBinding("value", vb);
column2.getChildren().add(column2Text);
HtmlOutputText column3Text=new HtmlOutputText();
vb =
FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.publisher}");
column3Text.setValueBinding("value", vb);
column3.getChildren().add(column3Text);
HtmlOutputText column4Text=new HtmlOutputText();
vb =
FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.edition}");
column4Text.setValueBinding("value", vb);
column4.getChildren().add(column4Text);
HtmlOutputText column5Text=new HtmlOutputText();
vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.title}");
column5Text.setValueBinding("value", vb);
column5.getChildren().add(column5Text);
HtmlOutputText column6Text=new HtmlOutputText();
vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.author}");
column6Text.setValueBinding("value", vb);
column6.getChildren().add(column6Text);
ResultSetDataModel dataModel=new ResultSetDataModel();
dataModel.setWrappedData(rs);
dataTable1.setValue(dataModel);
}
catch(SQLException e){}
catch(ClassNotFoundException e){}
finally{ rs.close();
stmt.close();
connection.close();
}
return null;
}
在连接 url 中,变量 <host> 是数据库主机,<port> 是数据库端口号(默认为 1521),<database> 是数据库实例。 再将以下导入语句添加到 Catalog.java backing bean 类中。
import java.sql.*;
import javax.faces.component.UIColumn;
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.HtmlOutputText;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.model.ResultSetDataModel;
在 Data Table tile 以及 header 和 footer tile 中用 h:panelGrid 标记替换 f:view 、html 和 h:form 标记。 这些标记是在包装 JSP tiles.jsp 中指定的。 下面显示了 tile catalog.jsp。
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<h:panelGrid>
<h:inputText binding="#{backing_catalog.inputText1}"/>
<h:commandButton value="Data Table"
binding="#{backing_catalog.commandButton1}"
action="#{backing_catalog.commandButton_action}"/>
<h:dataTable rows="5" binding="#{backing_catalog.dataTable1}">
<h:column binding="#{backing_catalog.column1}"/>
<h:column binding="#{backing_catalog.column2}"/>
<h:column binding="#{backing_catalog.column3}"/>
<h:column binding="#{backing_catalog.column4}"/>
<h:column binding="#{backing_catalog.column5}"/>
<h:column binding="#{backing_catalog.column6}"/>
</h:dataTable>
</h:panelGrid>
接下来,创建 header.jsp tile JSF JSP 页面。 将 JSFandTiles.jpg 和 Tiles.jpg jpeg 图像拷贝到 public_html 目录中。 在组件选项板中选择 Graphic Image 来将它们添加到 header tile 中。 在 Insert Graphic Image 框架中,选择 Browse 按钮来指定 Image URL。 在 Select Image Source 框架中,为 header tile 选择 JPEG JSF 和 Tiles.jpg。 单击 Open 按钮。 类似地,添加另一个 JPEG Tiles.jpeg。下面显示了 tile header.jsp。
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<h:panelGrid>
<h:graphicImage value="JSFandTiles.jpg"/>
<h:graphicImage value="Tiles.jpg"/>
</h:panelGrid>
接下来,添加 footer.jsp tile JSF JSP 页面。 将一个 文本为 "JSF Tiles Integration" 的 Output Label 添加到 footer tile 中。 下面显示了 tile footer.jsp。
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<h:panelGrid>
<h:outputLabel value="JSF Tiles Integration"/>
</h:panelGrid>
添加包装 JSP tiles.jsp(如下所示),它将定义 catalog.jsp tile 和 Tiles 应用程序的布局页面。
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %>
<html>
<f:view>
<head>
</head>
<body>
<f:subview id="catalog">
<h:form>
<tiles:insert definition="layout" flush="false">
<tiles:put name="table" value="catalog.jsp"/>
</tiles:insert>
</h:form>
</f:subview>
</body>
</f:view>
</html>
接下来,将 tiles-defs.xml Tiles 定义文件添加到 WEB-INF 目录中。 在 New Gallery 框架中选择 Web-Tier>Struts>Tiles Definition File。
 图 9 Tiles 定义文件
从 tiles-definitions 组件选项板中将元素添加到 tiles-defs.xml 配置文件中。
 图 10 tiles-definitions 组件选项板
tiles-defs.xml 配置文件指定了在 Tiles 应用程序中定义的 tile 以及 Tiles 应用程序的布局页面。 Tiles 应用程序中的 tile 可能在 tiles-defs.xml 文件或包装 JSP 中定义。 在示例 Tiles 应用程序中,header.jsp 和 footer.jsp tiles 都在 tiles-defs.xml 文件中定义,而 catalog.jsp tile 在包装 JSP 中定义。 下面显示了 tiles-defs.xml 文件。
<?xml version="1.0" encoding="windows-1252" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config.dtd">
<tiles-definitions>
<definition name="layout" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
</definition>
</tiles-definitions>
tile 的布局在 layout.jsp 页面中指定。
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %>
<tiles:importAttribute scope="request"/>
<h:panelGrid>
<f:subview id="header">
<tiles:insert attribute="header" flush="false"/>
</f:subview>
<f:subview id="table">
<tiles:insert attribute="table" flush="false"/>
</f:subview>
<f:subview id="footer">
<tiles:insert attribute="footer" flush="false"/>
</f:subview>
</h:panelGrid>
应用程序导航器中的 Tiles 应用程序的结构包括 tile、WEB-INF 目录中的应用程序配置文件和 WEB-INF/lib Jar 文件。
 图 11 Tiles 应用程序的结构
右键单击 tiles.jsp 并选择 Run 来运行 Tiles 应用程序。
 图 12 运行 Tiles 应用程序
在浏览器中显示了 Tiles 应用程序中的不同的 tile。 顶端的 tile 包含 JPEG 图像,中间的 tile 包含数据表,底下的 tile 包含输出标签。
 图 13 包含不同的 tile 的 Tiles 应用程序
指定一条 SQL 查询来生成数据表,并选择 Data Table 按钮。
 图 14 生成数据表
这将生成一个数据表,并且它将和其他 tile 一起在浏览器中显示。
 图 15 Tiles: JPEG 图像、数据表和页脚
祝贺您,您刚刚创建了一个包含 JSF 页面的 Tiles 应用程序!
Deepak Vohra (dvohra09@yahoo.com) 是获得 Sun 认证的 Java 1.4 程序员,并且是 Oracle 数据库 10g 认证初级人员。
将您的意见发送给我们 |