一個簡單的JSF例子(A simple JavaServer Faces example)
Figures 2a, 2b, and 2c show a very simple JSF application. The application's opening page contains a link that starts the application. That link points to a JSP page that displays a simple form. Because this simple application does not perform validation, you can click the Log In button without filling in the name and password fields, which will transport you to another JSP page that welcomes you to JavaServer Faces.
圖2a、2b、2c展示了一個簡單的JSF應用。這個應用的入口頁面包含一個啟動應用的鏈接。這個鏈接指向一個顯示一個簡單表單的JSP頁面。由于這個簡單的應用不進行驗證操作,所以你在表單的姓名和密碼域中不用輸入任何內容直接點擊Log In按鈕,你將被引導到另外一個歡迎你使用JSF的JSP頁面。

圖 2a 一個簡單的JSF應用

圖 2b JSF登錄界面

圖 2c歡迎信息
First, let's explore the logistics of implementing this simple application,
and JavaServer Faces applications in general. JSF requires the following jar files in the WEB-INF/lib directory:
首先,我們瀏覽一下這個簡單的應用和通常的JSF應用需要的支持。JSF需要在WEB-INF/lib目錄下存放有一下文件:
WEB-INF/lib/commons-beanutils.jar
WEB-INF/lib/commons-collections.jar
WEB-INF/lib/commons-digester.jar
WEB-INF/lib/commons-logging-api.jar
WEB-INF/lib/jsf-api.jar
WEB-INF/lib/jsf-ri.jar
WEB-INF/lib/jstl.jar
WEB-INF/lib/standard.jar
The jar files listed above are all you need for JSF applications. Even though, as we will see shortly, JSF applications typically use JSP tags implemented by the JSF implementation, there are no separate tag library descriptor (TLD) files because that information is contained in the jar files.
JSF應用需要的所有內容就是上面列舉的這些jar文件。當然,我們很快會注意到,JSF應用通常會使用JSF實現中實現的JSP 標簽,但是并不需要額外的標簽庫描述符(TLD)因為這些信息也包含在上面的jar文件中。
Here's a listing of the other files that comprise the application shown in Figure 2:
下面是一些我們這個JSF應用需要的其他文件的清單。
WEB-INF/web.xml
WEB-INF/classes/com/sabreware/listeners/SimpleContextListener.java
WEB-INF/classes/com/sabreware/appHandlers/SimpleApplicationHandler.java
/index.html
/index.jsp
示例1 WEB-INF/web.xml
Example 1. WEB-INF/web.xml
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Context Listener creates and sets the application handler -->
<listener>
<listener-class>
com.sabreware.listeners.SimpleServletContextListener
</listener-class>
</listener>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
The deployment descriptor listed above declares four things:
A servlet context listener
A controller servlet
A mapping for the controller servlet
A welcome file
上面的部署描述符聲明了四項內容:
1. 一個Servlet環境(Context)監聽器
2. 一個控制器Servlet
3. 控制器Servlet的映射
4. 一個歡迎頁面
The deployment descriptor listed in Example 1 associates the JSF controller servlet with the URL /faces/*, which causes the servlet container to map all URLs that start with /faces to the JSF controller servlet. JSF uses the controller servlet to control the JSF lifecycle.
部署描述符將/faces/*這樣的URL請求和JSF控制器servlet關聯起來,這使得servlet容器將把所有以/faces開頭的URL請求映射到這個JSF控制器servlet頁面。JSF使用這個控制器servlet控制JSF處理流程。
示例2 servlet運行環境監聽器
Example 2. WEB-INF/com/sabreware/listeners/SimpleServletContextListener
- package com.sabreware.listeners;
-
- import javax.servlet.*;
- import javax.faces.*;
- import javax.faces.lifecycle.*;
- import com.sabreware.appHandlers.SimpleApplicationHandler;
-
- public class SimpleServletContextListener implements ServletContextListener {
- public void contextInitialized(ServletContextEvent e) {
- LifecycleFactory factory = (LifecycleFactory)
- FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
-
- Lifecycle lifecycle = factory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
-
- lifecycle.setApplicationHandler(new SimpleApplicationHandler());
- }
- public void contextDestroyed(ServletContextEvent e) {
- // Nothing to do here
- }
- }
Servlet containers create servlet context listeners at application startup and invoke the listener's contextInitialized() method. When the application shuts down, the servlet container invokes the listener's contextDestroyed() method. The servlet context listener listed above creates an application handler and associates it with the JSF lifecycle. Application handlers handle application events and specify a URL that the JSF implementation subsequently forwards to, as illustrated by the application handler created in Example 2 and listed in Example 3.
servlet容器在應用啟動時生成servlet運行環境監聽器并調用監聽器的contextInitialized()方法。當應用終止時servlet容器調用監聽器的contextDestroyed()方法。上文中的servlet運行環境監聽器生成一個應用句柄并把它和運行流程關聯。應用句柄處理應用事件并且聲明JSF實現后續將要將請求前轉的URL,過程在示例2和示例3中說明。
示例3 SimpleApplicationHandler
Example 3. WEB-INF/com/sabreware/appHandlers/SimpleApplicationHandler
- package com.sabreware.appHandlers;
-
- import javax.faces.FactoryFinder;
- import javax.faces.context.FacesContext;
- import javax.faces.event.FacesEvent;
- import javax.faces.lifecycle.ApplicationHandler;
- import javax.faces.tree.TreeFactory;
-
- public class SimpleApplicationHandler implements ApplicationHandler {
- public boolean processEvent(FacesContext context, FacesEvent facesEvent) {
- TreeFactory treeFactory = (TreeFactory)FactoryFinder.
- getFactory(FactoryFinder.TREE_FACTORY);
- context.setResponseTree(
- treeFactory.getTree(context.getServletContext(),
- "/welcome.jsp"));
- return true;
- }
- }
In the JSF lifecycle's Render Response phase, the JSF implementation forwards to a URL. That URL represents a component tree, which is known as the response tree. The application handler listed above sets the response tree to /welcome.jsp, and the JSF implementation subsequently forwards to that URL after the application handler is invoked (in the Invoke Application phase of the JSF lifecycle). Our simple example only generates one application event—a form event generated when the Log In button is activated. JSF applications can generate two types of application events: form events and command events. Command events are generated when you click on a link.
在JSF處理流程中的響應合成階段,JSF實現將請求前轉到一個URL中。這個URL創建一個叫做響應樹的組件樹。上文的應用句柄將這個響應樹賦予/welcome.jsp,在應用句柄被激活(在調用Web應用階段)以后JSF實現緊接著前轉到這個URL。我們的這個簡單的應用僅生成一個應用事件——當Log In按鈕被按下時觸發的表單事件。JSF應用可以生成兩種類型的應用事件:表單事件和命令事件。命令事件通過點擊鏈接生成。
The servlet context listener listed in Example 2 and the application handler listed in Example 3 work hand in hand. The context listener creates the application handler, and the application handler specifies a URL that the JSF implementation forwards to when the login form is submitted.
示例2中的servlet運行環境監聽器和示例3中的應用句柄協同工作。運行環境監聽器生
成應用句柄,而應用句柄聲明了當login表單提交時JSF實現所應當前轉的URL。
The welcome file, /index.html, is listed in Example 4.
示例4 歡迎文件,/index.html
Example 4. /index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>A Simple JavaServer Faces Application</title>
</head>
<body>
<font size='4'>Welcome to a simple JavaServer Faces Application</font>
<p>
<a href='faces/index.jsp'>Click here to start the application</a>
<body>
</html>
The welcome file listed above creates a link to the first JSP page displayed by the application. All JSF applications must route the first JSP page displayed by the application through the JSF controller servlet. You can either provide an HTML page that contains a link to that JSP page, as illustrated in this example, or you can rely on the user to type the correct URL to start the application. Unfortunately, neither solution is very appealing; hopefully, JSF 1.0 will provide a mechanism to obviate this requirement.
上文的歡迎文件包含一個指向這個JSF應用顯示的第一個JSP頁面的鏈接。所有的JSF應都必須通過JSF控制器導向到各自應用所顯示的第一個JSP頁面。你可以象示例一樣提供一個包含指向這個JSP頁面的鏈接的HTML頁面,或者讓用戶直接輸入正確的URL地址以便激活應用。不幸的是,它們都不是很方便;希望在JSF 1.0版本中能提供滿足這個需求的機制。
The application's initial JSP page is listed in Example 5.
示例 5 應用的初始JSP頁面
Example 5. /index.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>A Simple JavaServer Faces Application</title>
</head>
<body>
<%@ taglib uri="http://java.sun.com/j2ee/html_basic/" prefix="faces" %>
<font size="4">Please enter your name and password</font>
<faces:usefaces>
<faces:form id="simpleForm" formName="simpleForm">
<table>
<tr>
<td>Name:</td>
<td><faces:textentry_input id="name"/></td>
</tr>
<tr>
<td>Password:</td>
<td><faces:textentry_secret id="password"/></td>
</tr>
</table>
<p><faces:command_button id="submit" commandName="Log In"/>
</faces:form>
</faces:usefaces>
</body>
</html>
The preceding JSP page is where most of the action takes place in our simple application. JSF provides JSP tags for all of the standard components that JSF supports. Those tags must be contained within the body of a <faces:usefaces> tag. The JSP page listed above uses the <faces:form> tag, which creates an HTML form, and the <faces:textentry_input> and <faces:textentry_secret> tags, which render an HTML text element and an HTML password element, respectively. The JSP page also uses the <faces:command_button> tag, which renders an HTML Submit button.
前面的這個JSP頁面包含了我們這個簡單的應用中大多數的動作。JSF提供了所有JSF支持的標準的組件的JSP 標簽。這些tags都必須包含在一個<faces:usefaces>標簽所標記的塊中。上面的頁面通過<faces:form>標簽生成一個HTML的表單,<faces:texentry_input> 標簽和<faces:textentry_secret>標簽分別生成一個HTML的文本輸入框和密碼輸入框。同樣通過<faces:command_button>標簽提供一個HTML的提交按鈕。
When the form in the preceding JSP page is submitted, the JSF lifecycle begins, and the application handler subsequently invokes. That handler specifies /welcome.jsp as the response tree, and the JSF implementation subsequently forwards to that JSP page, which is listed in Example 6.
當前面這個JSP頁面中的表單被提交時,JSF的處理流程開始了,應用句柄被調用。這個應用句柄聲明/welcome.jsp作為響應樹,并且JSF實現隨之將請求前轉到這個JSP頁面中,示例 6說明了這個處理過程。
示例6 /welcome.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>A Simple JavaServer Faces Application</title>
</head>
<body>
Welcome to JavaServer Faces!
</body>
</html>
Now that we've seen how a simple JSF application works, let's extend that application by adding field validation.
現在我們已經看到了一個簡單的JSF應用是如何工作的,下面讓我們擴展一下加入字段的驗證。
用JSF進行驗證
JavaServer Faces provides built-in validation and a framework for creating custom validators. Built-in validation is discussed below; custom validation will be discussed in Part 2.
JSF提供了內建的驗證和創建定制的驗證的框架。我們首先討論內建的驗證,定制的驗證將在第二部分討論。
內建的驗證(Built-in validation)
JavaServer Faces provides the following built-in validators:
JSF提供了以下內建的驗證器:
DoubleRangeValidator
LengthValidator
LongRangeValidator
RequiredValidator
StringRangeValidator
The preceding list of validators represent class names. Those classes reside in the javax.faces.validator package. The DoubleRangeValidator and LongRangeValidator validate that a request parameter (which is always a string) can convert to either a double or long, respectively, and that those values fall within a specified range. The LengthValidator checks the string length of a request parameter against minimum or maximum values. The RequiredValidator requires a non-null value for a given field. The StringRangeValidator converts a string into either a long or a double and checks that value against specified minimum or maximum values.
前面羅列的是驗證器的類名。這些類都在javax.faces.validator包中。DoubleRangeValidator 和LongRangeValidator驗證一個請求參數是否可以轉換成為一個雙精度浮點數或長整數 并且在某個指定的范圍內。LengthValidator驗證闡述的長度是否在指定的最小和最大值之間。RequiredValidator檢驗必須提供的字段是否有非空的數值。StringRangeValidator將一個字符串轉換為長整數或者雙精度浮點數同時驗證是否在指定的最小和最大值之間。

圖 3 JSF內建的驗證器
Figure 3 shows an error message generated by a length validator. The minimum length was specified as three, but the value entered in the corresponding field was only two characters, so a validation error and corresponding error message were generated when the field's corresponding form was submitted.
圖3顯示了長度驗證器生成的錯誤信息。最短長度聲明為3,但是輸入的數據的長度為2,所以當該頁面提交的時候出現一個驗證錯誤同時生成了錯誤信息。
Example 7 lists the JSP page shown in Figure 3.
示例 7 圖 3中的JSP頁面。
示例 7. 使用長度驗證器(Use the LengthValidator)
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN'>
<html>
<head>
<title>A Simple JavaServer Faces Application</title>
</head>
<body>
<%@ taglib uri='http://java.sun.com/j2ee/html_basic/' prefix='faces' %>
<font size='4'>Please enter your name and password</font>
<faces:usefaces>
<faces:form id='simpleForm' formName='simpleForm'>
<table>
<tr>
<td>Name:</td>
<td>
<faces:textentry_input id='name'>
<faces:validator
className='javax.faces.validator.LengthValidator'/>
<faces:attributename=
'javax.faces.validator.LengthValidator.MINIMUM'
value='3'/>
</faces:textentry_input>
</td>
<td>
<faces:validation_message componentId='name'/>
</td>
</tr>
<tr>
<td>Password:</td>
<td>
<faces:textentry_secret id='password'/>
</td>
</tr>
</table>
<p><faces:command_button id='submit' commandName='Log In'/>
</faces:form>
</faces:usefaces>
</body>
</html>
As evidenced by the preceding JSP page, JSF validators are easy to use: simply add a <faces:validator> tag and one or more <faces:attribute> tags to the body of the component you want to validate. Validators store error
messages in the JSF context when validation fails; you can extract those error messages with the <faces:validation_message>, which lets you specify the component to which those messages apply.
就像前面的JSP頁面所說明的,JSF的驗證器是非常易于使用的:簡單的添加一個<faces:validator>標簽和一個或幾個<faces:attribute>標簽到你希望進行驗證的組件中。當驗證失敗的時候,驗證器會將錯誤信息存儲于JSF的運行環境中;你可以使用<faces:validation_message>解析這些信息,它是用于標識具體哪個組件將使用這些信息的。
仍有更多(More to come)
JSF represents a new paradigm for developing J2EE applications.With a well-defined request processing lifecycle, event handling, validation, and a rich component hierarchy for developing complex custom components that can write to multiple devices, JSF will greatly facilitate the development of J2EE application Web tiers.
JSF提出了一種新的開發J2EE應用的框架。通過良好定義的請求處理流程、事件處理、驗證機制和可以用于多種設備的用于開發復雜的定制組件的豐富的組件庫,JSF將極大的推動基于Web的多層的J2EE應用的開發。
In this article, I introduced basic JavaServer Faces concepts, including the JSF lifecycle, using JSF standard components and their corresponding JSP tags, and built-in validation. In Part 2, I will discuss more advanced JSF features, including custom validation, internationalization, using model objects, and implementing custom components.
通過本文,我介紹了基本的JSF概念,包括JSF處理流程、使用JSF標準組件和對應的標簽和內建的驗證機制。在第二部分中,我將討論更多的JSF高級特性,包括定制驗證、國際化支持、使用模型對象和實現定制組件。
About the author
David Geary is the author of Core JSTL Mastering the JSP Standard Tag Library (Prentice Hall, 2002; ISBN: 0131001531); Advanced JavaServer Pages (Prentice Hall, 2001; ISBN: 0130307041); and the Graphic Java series (Sun Microsystems Press). David has been developing object-oriented software with numerous object-oriented languages for 18 years. Since the GOF Design Patterns book was published in 1994, David has been an active proponent of design patterns and has used and implemented design patterns in Smalltalk, C++, and Java. In 1997, David began working full-time as an author and occasional speaker and consultant. David is a member of the expert group defining the JSP Standard Tag Library, and is a contributor to the Apache Struts JSP framework. He writes JavaWorld's Java Design Patterns column.
Resources
? Download the source code that accompanies this article:
http://www.javaworld.com/jw-11-2002/jsf/jw-1129-jsf.jar ? An integration strategy for Struts and JavaServer Faces:
http://www.mail-archive.com/struts-dev@jakarta.apache.org/msg08457.html ? Download the JSF specification, the reference implementation, two sample applications, and a JSF tutorial from:
http://java.sun.com/j2ee/javaserverfaces ? Browse the JavaServer Pages section of JavaWorld's Topical Index:
http://www.javaworld.com/channel_content/jw-jsp-index.shtml ? Browse the Enterprise Java section of JavaWorld's Topical Index:
http://www.javaworld.com/channel_content/jw-enterprise-index.shtml ? David Geary's Java Design Patterns column in JavaWorld:
http://www.javaworld.com/columns/jw-java-design-patterns-index.shtml ? Visit JavaWorld's Enterprise Java discussion:
http://forums.devworld.com/webx?50@@.ee6b80a ? Sign up for JavaWorld's free weekly Enterprise Java email newsletter:
http://www.javaworld.com/subscribe ? You'll find a wealth of IT-related articles from our sister publications at
IDG.net