A first look at JavaServer Faces(jsf 2)
一個簡單的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應(yīng)用。這個應(yīng)用的入口頁面包含一個啟動應(yīng)用的鏈接。這個鏈接指向一個顯示一個簡單表單的JSP頁面。由于這個簡單的應(yīng)用不進(jìn)行驗(yàn)證操作,所以你在表單的姓名和密碼域中不用輸入任何內(nèi)容直接點(diǎn)擊Log In按鈕,你將被引導(dǎo)到另外一個歡迎你使用JSF的JSP頁面。

圖 2a 一個簡單的JSF應(yīng)用

圖 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:
首先,我們?yōu)g覽一下這個簡單的應(yīng)用和通常的JSF應(yīng)用需要的支持。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應(yīng)用需要的所有內(nèi)容就是上面列舉的這些jar文件。當(dāng)然,我們很快會注意到,JSF應(yīng)用通常會使用JSF實(shí)現(xiàn)中實(shí)現(xiàn)的JSP 標(biāo)簽,但是并不需要額外的標(biāo)簽庫描述符(TLD)因?yàn)檫@些信息也包含在上面的jar文件中。
Here's a listing of the other files that comprise the application shown in Figure 2:
下面是一些我們這個JSF應(yīng)用需要的其他文件的清單。
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
上面的部署描述符聲明了四項內(nèi)容:
1. 一個Servlet環(huán)境(Context)監(jiān)聽器
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關(guān)聯(lián)起來,這使得servlet容器將把所有以/faces開頭的URL請求映射到這個JSF控制器servlet頁面。JSF使用這個控制器servlet控制JSF處理流程。
示例2 servlet運(yùn)行環(huán)境監(jiān)聽器
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容器在應(yīng)用啟動時生成servlet運(yùn)行環(huán)境監(jiān)聽器并調(diào)用監(jiān)聽器的contextInitialized()方法。當(dāng)應(yīng)用終止時servlet容器調(diào)用監(jiān)聽器的contextDestroyed()方法。上文中的servlet運(yùn)行環(huán)境監(jiān)聽器生成一個應(yīng)用句柄并把它和運(yùn)行流程關(guān)聯(lián)。應(yīng)用句柄處理應(yīng)用事件并且聲明JSF實(shí)現(xiàn)后續(xù)將要將請求前轉(zhuǎn)的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處理流程中的響應(yīng)合成階段,JSF實(shí)現(xiàn)將請求前轉(zhuǎn)到一個URL中。這個URL創(chuàng)建一個叫做響應(yīng)樹的組件樹。上文的應(yīng)用句柄將這個響應(yīng)樹賦予/welcome.jsp,在應(yīng)用句柄被激活(在調(diào)用Web應(yīng)用階段)以后JSF實(shí)現(xiàn)緊接著前轉(zhuǎn)到這個URL。我們的這個簡單的應(yīng)用僅生成一個應(yīng)用事件——當(dāng)Log In按鈕被按下時觸發(fā)的表單事件。JSF應(yīng)用可以生成兩種類型的應(yīng)用事件:表單事件和命令事件。命令事件通過點(diǎn)擊鏈接生成。
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運(yùn)行環(huán)境監(jiān)聽器和示例3中的應(yīng)用句柄協(xié)同工作。運(yùn)行環(huán)境監(jiān)聽器生
成應(yīng)用句柄,而應(yīng)用句柄聲明了當(dāng)login表單提交時JSF實(shí)現(xiàn)所應(yīng)當(dāng)前轉(zhuǎn)的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應(yīng)用顯示的第一個JSP頁面的鏈接。所有的JSF應(yīng)都必須通過JSF控制器導(dǎo)向到各自應(yīng)用所顯示的第一個JSP頁面。你可以象示例一樣提供一個包含指向這個JSP頁面的鏈接的HTML頁面,或者讓用戶直接輸入正確的URL地址以便激活應(yīng)用。不幸的是,它們都不是很方便;希望在JSF 1.0版本中能提供滿足這個需求的機(jī)制。
The application's initial JSP page is listed in Example 5.
示例 5 應(yīng)用的初始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頁面包含了我們這個簡單的應(yīng)用中大多數(shù)的動作。JSF提供了所有JSF支持的標(biāo)準(zhǔn)的組件的JSP 標(biāo)簽。這些tags都必須包含在一個<faces:usefaces>標(biāo)簽所標(biāo)記的塊中。上面的頁面通過<faces:form>標(biāo)簽生成一個HTML的表單,<faces:texentry_input> 標(biāo)簽和<faces:textentry_secret>標(biāo)簽分別生成一個HTML的文本輸入框和密碼輸入框。同樣通過<faces:command_button>標(biāo)簽提供一個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.
當(dāng)前面這個JSP頁面中的表單被提交時,JSF的處理流程開始了,應(yīng)用句柄被調(diào)用。這個應(yīng)用句柄聲明/welcome.jsp作為響應(yīng)樹,并且JSF實(shí)現(xiàn)隨之將請求前轉(zhuǎn)到這個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.
現(xiàn)在我們已經(jīng)看到了一個簡單的JSF應(yīng)用是如何工作的,下面讓我們擴(kuò)展一下加入字段的驗(yàn)證。
用JSF進(jìn)行驗(yàn)證
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提供了內(nèi)建的驗(yàn)證和創(chuàng)建定制的驗(yàn)證的框架。我們首先討論內(nèi)建的驗(yàn)證,定制的驗(yàn)證將在第二部分討論。
內(nèi)建的驗(yàn)證(Built-in validation)
JavaServer Faces provides the following built-in validators:
JSF提供了以下內(nèi)建的驗(yàn)證器:
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.
前面羅列的是驗(yàn)證器的類名。這些類都在javax.faces.validator包中。DoubleRangeValidator 和LongRangeValidator驗(yàn)證一個請求參數(shù)是否可以轉(zhuǎn)換成為一個雙精度浮點(diǎn)數(shù)或長整數(shù) 并且在某個指定的范圍內(nèi)。LengthValidator驗(yàn)證闡述的長度是否在指定的最小和最大值之間。RequiredValidator檢驗(yàn)必須提供的字段是否有非空的數(shù)值。StringRangeValidator將一個字符串轉(zhuǎn)換為長整數(shù)或者雙精度浮點(diǎn)數(shù)同時驗(yàn)證是否在指定的最小和最大值之間。

圖 3 JSF內(nèi)建的驗(yàn)證器
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顯示了長度驗(yàn)證器生成的錯誤信息。最短長度聲明為3,但是輸入的數(shù)據(jù)的長度為2,所以當(dāng)該頁面提交的時候出現(xiàn)一個驗(yàn)證錯誤同時生成了錯誤信息。
Example 7 lists the JSP page shown in Figure 3.
示例 7 圖 3中的JSP頁面。
示例 7. 使用長度驗(yàn)證器(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的驗(yàn)證器是非常易于使用的:簡單的添加一個<faces:validator>標(biāo)簽和一個或幾個<faces:attribute>標(biāo)簽到你希望進(jìn)行驗(yàn)證的組件中。當(dāng)驗(yàn)證失敗的時候,驗(yàn)證器會將錯誤信息存儲于JSF的運(yùn)行環(huán)境中;你可以使用<faces:validation_message>解析這些信息,它是用于標(biāo)識具體哪個組件將使用這些信息的。
仍有更多(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提出了一種新的開發(fā)J2EE應(yīng)用的框架。通過良好定義的請求處理流程、事件處理、驗(yàn)證機(jī)制和可以用于多種設(shè)備的用于開發(fā)復(fù)雜的定制組件的豐富的組件庫,JSF將極大的推動基于Web的多層的J2EE應(yīng)用的開發(fā)。
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標(biāo)準(zhǔn)組件和對應(yīng)的標(biāo)簽和內(nèi)建的驗(yàn)證機(jī)制。在第二部分中,我將討論更多的JSF高級特性,包括定制驗(yàn)證、國際化支持、使用模型對象和實(shí)現(xiàn)定制組件。
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