JavaServer Faces 2.0 简介
JavaServer Faces (JSF) 是 Java Web 应用程序的一个用户界面 (user interface, UI) 框架。设计 JSF 的目的在于,极大地缓解在 Java 应用服务器上运行的应用程序的编写和维护的压力,并将这些应用程序的 UI 重新呈现给目标客户端。JSF 具有如下易用性的优点:
- 可以轻松地通过一组可重用的 UI 组件来构造一个 UI
- 简化了应用程序数据与 UI 之间进行迁移的过程
- 有助于管理服务器请求中的 UI 状态
- 提供了将客户端生成的事件连接到服务器端应用程序代码的简单模型
- 可以轻松地生成和重用定制的 UI 组件
有关 JSF 框架的深入介绍,请参见 Java EE 6 教程的第 5 章:JavaServer Faces 技术。
本教程将对如何使用 NetBeans IDE 为 Web 应用程序提供 JSF 2.0 支持进行说明。首先会为基本的 Web 应用程序添加 JSF 2.0 框架支持,然后执行以下操作:
- 创建一个 JSF 受管 Bean 来处理请求数据,
- 将受管 Bean 连接到应用程序的 Web 页,然后
- 将 Web 页转换为 Facelets 模板文件。
NetBeans IDE 为 JavaServer Faces 提供了长期支持。随着 JSF 2.0 和 Java EE 6 的发布,NetBeans IDE 专门提供了对 JSF 2.0 的支持。有关详细信息,请参见 NetBeans IDE 中的 JSF 2.0 支持。
目录

要学完本教程,您需要具备以下软件和资源。
注意:
- NetBeans IDE Java 包还包括本教程所需的 GlassFish Server 3.0.1(一种 Java EE 6 兼容的服务器)。
- 要将您的项目与工作解决方案进行比较,请下载完成的样例项目。
将 JSF 2.0 支持添加到 Web 应用程序
首先,在 IDE 中打开 jsfDemo Web 应用程序项目。在 IDE 中打开该项目后,可以使用该项目的“属性”窗口将框架支持添加到该项目中。
使用 IDE 还可以创建具有 JSF 2.0 支持的新项目。有关详细信息,请参见创建具有 JSF 2.0 支持的新项目。
- 单击 IDE 主工具栏上的“打开项目”(
) 按钮,或者按 Ctrl-Shift-O 组合键(在 Mac 上为 ⌘-Shift-O 组合键)。
- 在“打开项目”对话框中,导航到计算机上存储已解压缩教程项目的位置。选择该项目,然后单击“打开项目”以在 IDE 中打开。
- 运行该项目以查看其在浏览器中的外观。可以在“项目”窗口中右键单击
jsfDemo 项目节点并选择“运行”,也可以单击主工具栏上的“运行项目”(
) 按钮。该项目将打包并部署到 GlassFish 服务器,并且您的浏览器随即打开以显示欢迎页 (index.xhtml)。

- 单击 "Submit" 按钮。响应页 (
response.xhtml) 显示如下:
目前欢迎页和响应页为静态页面,另外还有 stylesheet.css 文件和 duke.png 图像,这些都是通过浏览器访问的仅有的应用程序文件。
- 在“项目”窗口(Ctrl-1 组合键;在 Mac 上为 ⌘-1 组合键)中,右键单击项目节点,然后选择“属性”。将显示“项目属性”窗口。
- 选择“框架”类别,然后单击“添加”按钮。在显示的对话框中,选择 "JavaServer Faces",然后单击“确定”。
在选择了 JavaServer Faces 之后,各种配置选项就变为可用选项了。在“库”标签下面,可以指定项目访问 JSF 2.0 库的方式。缺省选项是使用服务器 (GlassFish Server 3.0.1) 附带的库。但是,IDE 还捆绑了 JSF 2.0 库。(如果希望您的项目使用这些库,可以选择“已注册的库”选项。)

- 单击“配置”标签。可以指定 Faces Servlet 在项目的部署描述符中注册的方式。还可以指定是否需要在项目中使用 Facelets 或 JSP 页。

- 单击“确定”以完成更改并退出“项目属性”窗口。
在将 JSF 支持添加到项目中后,该项目的 web.xml 部署描述符修改为如下内容:(更改内容以粗体显示。)
<web-app version="3.0" 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-app_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
重要说明:如果 <welcome-file> 条目不包含 "faces/",则应手动添加该内容。这可以确保项目的欢迎页 (index.xhtml) 先传递 Faces servlet,然后再显示在浏览器中。它是正确呈现 Facelets 标记库组件所必需的。有关详细信息,请参见问题 182277。
在项目中注册 Faces Servlet,并且在请求 index.xhtml 欢迎页面时,该页将立即通过 Faces Servlet 进行传递。此外,请注意已添加了一个 PROJECT_STAGE 上下文参数的条目。将此参数设置为 "Development",可在调试应用程序时为您提供有用的信息。有关详细信息,
请参见 http://blogs.oracle.com/rlubke/entry/jsf_2_0_new_feature2。
通过在“项目”窗口中展开项目的“库”节点,可以查找 JSF 库。如果您使用的是 GlassFish 服务器的缺省库,则这些缺省库为 GlassFish Server 3.0.1 节点下列出的 jsf-api.jar 和 jsf-impl.jar 文件。
IDE 的 JSF 2.0 支持主要包括大量特定于 JSF 的向导以及由 Facelets 编辑器提供的特殊功能。您将在以下步骤中了解这些功能。有关详细信息,请参见 NetBeans IDE 中的 JSF 2.0 支持。
创建受管 Bean
您可以使用 JSF 的受管 Bean 来处理用户数据并在请求之间保留这些数据。受管 Bean 是一个 POJO(Plain Old Java Object,简单的传统 Java 对象),可用于存储数据,并由容器(例如,GlassFish 服务器)使用 JSF 框架来管理。
POJO 本质上是一个 Java 类,包含了一个无参数的公共构造函数,并且该类遵循其属性的 JavaBeans 命名约定。
请看通过运行项目所生成的静态页面,您需要一种机制:用于确定用户输入的数字是否与当前选择的一个数字相匹配,并且返回与此结果相应的视图。使用 IDE 的受管 Bean 向导来创建受管 Bean 以实现此目的。您在下一部分创建的 Facelets 页将需要访问用户键入的数字和生成的响应。要启用此功能,请将 userNumber 和 response 属性添加到受管 Bean 中。
将受管 Bean 连接到页面
JSF 的一个主要目的就是不需要编写样板代码来管理 POJO 及其与应用程序视图的交互。在上一部分中,您已看到这样的示例,当运行应用程序时,JSF 实例化了一个 UserNumberBean 对象。此概念被称为控制反转 (Inversion of Control, IoC),可以让容器负责管理应用程序的某些部分,否则这些部分就需要开发者编写重复的代码。
在上一部分,您已创建了一个生成 0 到 10 之间的随机数字的受管 Bean。还创建了两个属性,userNumber 和 response,分别代表用户输入的数字,和对用户所做猜测的响应。
在此部分,您将了解如何在 Web 页中使用 UserNumberBean 及其属性。JSF 通过其表达式语言 (expression language, EL) 来实现此功能。使用表达式语言将属性值绑定到应用程序 Web 页中包含的 JSF UI 组件。此部分还将说明演示如何利用 JSF 2.0 的隐式导航功能在索引页和响应页之间进行导航。
IDE 通过其代码完成和文档功能为此操作提供支持,您可以在编辑器中的项目上按 Ctrl-空格键调用这些功能。
首先对 index.xhtml 进行更改,然后对 response.xhtml 进行更改。在这两个页面中,将 HTML 表单元素替换成其 JSF 的对应元素,如 JSF HTML 标记库中定义的元素。然后,使用 JSF 表达式语言将属性值与选定的 UI 组件绑定在一起。
应用 Facelets 模板
Facelets 已成为 JSF 2.0 的标准显示技术。Facelets 是一个轻量级的模板框架,它支持所有 JSF UI 组件,并用于生成和呈现应用程序视图的 JSF 组件树。在出现 EL 错误时,Facelets 还通过检查栈跟踪、组件树和作用域变量来提供开发支持。
尽管您也许还没有意识到,到目前为止您在本教程中所使用的 index.xhtml 和 response.xhtml 文件就是 Facelets 页。Facelets 页使用 .xhtml 扩展名,因为您是在 JSF 2.0 项目中工作(JSF 2.0 库包含了 Facelets JAR 文件。),所以视图可以正确地呈现 JSF 组件树。
此部分旨在帮助您熟悉 Facelets 模板。对于包含许多视图的项目,应用一个为多个视图定义了结构和外观的模板文件通常是很有用的。在为请求提供服务时,应用程序将动态准备的内容插入到模板文件中,并将结果发送回客户端。尽管本项目仅包含两个视图(欢迎页面和响应页面),但很容易看到这两个视图包含了大量的重复内容。可以将此重复内容提取到 Facelets 模板中,然后创建模板客户端文件来处理特定于欢迎页面和响应页面的内容。
IDE 提供了一个用于创建 Facelets 模板的“Facelets 模板”向导,和一个用于创建依赖于模板的文件的“Facelets 模板客户端”向导。此部分将使用这些向导。
注意:IDE 还提供了可为项目创建各个 Facelets 页的 JSF 页向导。有关详细信息,请参见 NetBeans IDE 中的 JSF 2.0 支持。
创建 Facelets 模板文件
- 创建一个 Facelets 模板文件。按 Ctrl-N 组合键(在 Mac 上为 ⌘-N 组合键)来打开文件向导。选择 "JavaServer Faces" 类别,然后选择“Facelets 模板”。单击“下一步”。
- 键入
template 作为文件名。
- 从八种布局样式中选择任意一种,然后单击“完成”。(您将使用现有的样式表,所以无论您选择的是哪种布局样式都没有关系。)
该向导会基于您的选择生成 template.xhtml 文件和附带的样式表,并将这些文件置于项目 Web 根目录内的 resources > css 文件夹中。
完成向导之后,模板文件在编辑器中打开。要在浏览器中查看模板,请右键单击编辑器并选择“视图”。
- 检查模板文件标记。请注意以下要点:
- 在页面的
<html> 标记中声明了 facelets 标记库。标记库具有 ui 前缀。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
- Facelets 页使用
<h:head> 和 <h:body> 标记而不是 html 的 <head> 和 <body> 标记。通过使用这些标记,Facelets 可以构造一个包含整个页面的组件树。
- 该页引用了在完成向导操作时同时创建的样式表。
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
<title>Facelets Template</title>
</h:head>
- 对于每个与所选择布局样式相关联的分栏,页面主体中都使用
<ui:insert> 标记。每个 <ui:insert> 标记都有一个 name 属性用于标识分栏。例如:
<div id="top">
<ui:insert name="top">Top</ui:insert>
</div>
- 重新检查欢迎和响应页面。这两个页面之间唯一更改的内容是包含在灰色方块中的标题和文本。因此,模板可以提供其余所有内容。
- 将您的模板文件的全部内容替换为如下内容。
<?xml version='1.0' encoding='UTF-8' ?>
<!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">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="css/stylesheet.css" rel="stylesheet" type="text/css" />
<title><ui:insert name="title">Facelets Template</ui:insert></title>
</h:head>
<h:body>
<div id="left">
<ui:insert name="box">Box Content Here</ui:insert>
</div>
</h:body>
</html>
上述代码实现了以下更改:
- 项目的
stylesheet.css 文件替换了由向导创建的模板样式表引用。
- 除了一个名为
box 的标记之外,所有 <ui:insert> 标记(及其包含的 <div> 标记)都已删除。
- 在页面标题周围放置了
<ui:insert> 标记对,并命名为 title。
- 将
index.xhtml 或 response.xhtml 文件中的相关代码复制到模板中。将以下粗体显示的内容添加到模板文件的 <h:body> 标记中。
<h:body>
<div id="mainContainer">
<div id="left" class="subContainer greyBox">
<ui:insert name="box">Box Content Here</ui:insert>
</div>
<div id="right" class="subContainer">
<img src="duke.png" alt="Duke waving" />
</div>
</div>
</h:body>
- 运行项目。当欢迎页面在浏览器中打开时,将 URL 修改为以下内容:
http://localhost:8080/jsfDemo/faces/template.xhtml
模板文件将如下所示:
此项目现在包含了一个可为所有视图提供外观和结构的模板文件。您现在可以创建调用了模板的客户端文件。
创建模板客户端文件
为欢迎页和响应页创建模板客户端文件。将欢迎页面的模板客户端文件命名为 greeting.xhtml。对于响应页,其模板客户端文件则为 response.xhtml。
greeting.xhtml
- 按 Ctrl-N 组合键(在 Mac 上为 ⌘-N 组合键)以打开“新建文件”向导。选择 "JavaServer Faces" 类别,然后选择“Facelets 模板客户端”。单击“下一步”。
- 键入
greeting 作为文件名。
- 单击“模板”字段旁边的“浏览”按钮,然后使用显示的对话框导航到上一部分创建的
template.xhtml 文件。

- 单击“完成”。将生成新的
greeting.xhtml 模板客户端文件并显示在编辑器中。
- 检查标记。请注意以粗体突出显示的内容。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="./template.xhtml">
<ui:define name="title">
title
</ui:define>
<ui:define name="box">
box
</ui:define>
</ui:composition>
</body>
</html>
模板客户端文件通过使用 <ui:composition> 标记的 template 属性来引用模板。因为模板包含了 title 和 box 的 <ui:insert> 标记,所以该模板客户端包含了这两个名称的 <ui:define> 标记。您在 <ui:define> 标记之间指定的内容就是将插入到模板中相应名称的 <ui:insert> 标记之间的内容。
- 指定
greeting 作为文件的标题。进行以下更改(粗体显示)。
<ui:define name="title">
Greeting
</ui:define>
- 切换到
index.xhtml 文件(按 Ctrl-Tab 组合键),然后复制通常会出现在灰色方块(显示在所呈现的页面中)中的内容。然后切换回 greeting.xhtml,并将其粘贴到模板客户端文件中。(更改内容以粗体显示。)
<ui:define name="box">
<h4>Hi, my name is Duke!</h4>
<h5>I'm thinking of a number
<br/>
between
<span class="highlight">0</span> and
<span class="highlight">10</span>.</h5>
<h5>Can you guess it?</h5>
<h:form>
<h:inputText size="2" maxlength="2" value="#{UserNumberBean.userNumber}" />
<h:commandButton id="submit" value="submit" action="response" />
</h:form>
</ui:define>
- 为该文件声明 JSF HTML 标记库。将光标置于任意一个被标记为错误的标记(任何使用 "
h" 前缀的标记)上,然后按 Ctrl-空格键。然后从代码完成建议列表中选择标记。标记库名称空间将被添加到该文件的 <html> 标记中(如以下粗体所示),并且错误指示符将消失。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
如果将光标置于 <h:form> 中的 "m" 后面,然后按 Ctrl-空格键,则名称空间将自动添加到文件中。如果在按 Ctrl-空格键时仅有一个逻辑选项可用,则会立即将其应用于文件中。当在标记上调用代码完成时,会自动声明 JSF 标记库。
response.xhtml
因为此项目已经包含了一个名为 response.xhtml 的文件,并且您现在已经知道了模板客户端文件应该是什么样的,那么就请将现有的 response.xhtml 修改为模板客户端文件。(就本教程而言,只需复制和粘贴已提供的代码即可。)
- 在编辑器中打开
response.xhtml。(如果该文件已打开,请按 Ctrl-Tab 组合键并选择该文件。)将整个文件的内容替换为以下代码。
<?xml version='1.0' encoding='UTF-8' ?>
<!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">
<body>
<ui:composition template="./template.xhtml">
<ui:define name="title">
Response
</ui:define>
<ui:define name="box">
<h4><h:outputText escape="false" value="#{UserNumberBean.response}"/></h4>
<h:form prependId="false">
<h:commandButton id="backButton" value="Back" action="greeting" />
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
请注意,该文件除了在 title 和 box 的 <ui:define> 标记之间指定的内容外,与 greeting.xhtml 是相同的。
- 在此项目的
web.xml 部署描述符中,修改欢迎文件条目以使 greeting.xhtml 成为在运行此应用程序时所打开的页面。
在“项目”窗口中,双击“配置文件”> "web.xml" 以在编辑器中将其打开。在“页面”标签下面,将“欢迎文件”字段更改为 "faces/greeting.xhtml"。

- 运行该项目以查看其在浏览器中的外观。按 F6 键(在 Mac 上为 fn-F6 组合键),或者单击主工具栏上的“运行项目”(
) 按钮。该项目将被部署到 GlassFish 服务器并在浏览器中打开。
使用了 Facelets 模板和模板客户端文件,该应用程序的行为方式仍与以前一样。通过将应用程序欢迎页和响应页中的重复代码提取出来,可以成功减小应用程序的大小,并避免在以后添加更多页面时可能编写更多的重复代码。在使用大型项目时,这样便可以更有效更轻松地维护开发。
另请参见
有关 JSF 2.0 的更多信息,请参见以下资源。