JSF技术介绍(JavaServer Faces Technology:chapter 9)《注:未完成》

    JavaServer Faces(以下简称JSF)技术是基于java技术Web应用的服务器端用户界面组件框架。

    JSF技术的主要组件有以下:  

    • 代表用户界面(以下简称UI)组件并且能管理其状态的API,处理事件,服务器端数据验证,数据转换,定义页面导航,支持国际化和易访问,并且对这些功能提供可扩展的能力。
    • 两种JSP定制标签库,即表达JSP页面中UI组件的标签库和把组件联系组织(wiring )到服务器端对象的标签库。
       定义良好的编程模型和标签库在很大程度上减低了构建和维护具有服务器端UI的Web应用的负担。只需要很少的努力,你就能可以
    • 通过添加组件标签把组件拖到页面上
    • 将组件产生的事件和服务器端代码联系起来
    • 将页面上的UI组件和服务器端数据绑定
    • 应用可重用和可扩展的组件构造UI
    • 跨requests保存或恢复UI状态

As shown in Figure 9-1, the user interface you create with JavaServer Faces technology (represented by myUI in the graphic) runs on the server and renders back to the client.


       这个JSP页面myform.jsp,就是一个JSF页面,即一个包含了JSF标签的JSP页面。它通过应用JSF技术定义的标签库表现UI组件。这个Web应用的UI组件(由图中的myUI代表)管理被JSP引用的对象。这些对象包括:

    • 映射到JSP页面上的标签的UI组件对象
    • 任何事件监听器,数据验证器,转换器都在组件上注册
    • 包装了数据和组件的应用特有功能的JavaBeans组件
       这一章是对JSF技术的概述。在列举了应用JSF技术的诸多好处并解释了什么是JSF应用之后,以下列出了研究这种技术的用户的不同的应用开发角色。会通过一个简单应用详细说明各个角色的应用开发。最后,这章将用一个来自于简单应用的页面来总结JSF页面的生存周期。

 

 

JSF技术的优点

        JSF技术一个最好的优点是它在行为和表现之间提供了一个清晰的划分。用JSP技术构建的Web应用部分完成了这种划分。但是,一个JSP的应用不能映射HTTP请求到特定组件事件,也不能将服务器上的UI元素作为有状态对象来管理,但一个JSF应用能做到。JSF技术允许你构建能将行为和表现出色的分开的的Web应用,而传统上这只有客户端UI架构才能提供。 

       这种针对逻辑和表现的划分可以使Web应用开发团队的成员集中精力关注他/她自己的开发进程,并且提供了一个简单的变成模型来将这些不同开发成员的进程链接起来。举个例子,页面设计者不需要任何编程就可以应用JSF技术里的UI组件在web页面里连接到服务器端对象,也不需要写任何脚本。

       JSF技术的另一个重要目标就是平衡我们所熟悉的UI组件和web层主题,当然并取限制你应用脚本技术或标记语言。尽管JSF技术包含了JSP标签库来显示JSP页面上的组件,JSF技术API直接处于Servlet API之上,如Figure 2-2所示。这一层API支持几个重要的应用用例,比如应用其他表现技术而不是JSP,从组件类创建你自己的定制组件,针对不同的客户端设备产生输出。

       最重要的使,JSF技术提供了一个胖的架构来管理组件的状态,处理组件数据,验证用户的输入,处理事件。


  什么是JSF应用?

        在绝大多数情况下,一个JSF应用和其他Java应用没什么不同。一个典型的JSF应用包括以下部分:

    • 一组JSP页面(当然你也可以不用JSP,而用你自己的表现技术)
    • 一组后台beans,这些beans组件定义了页面上的UI组件的属性和功能
    • 一个配置应用的资源文件,这个文件定义了文件导航规则,并配置beans和其他定制对象,比如定制组件
    • 一个部署描述文件(web.xml
    • 也许一组由应用开发者创建的定制对象,这些对象可能包括定制组件,数据验证器,转换器或监听器
    • 一组用来在页面上显示定制对象的定制标签

         一个包含了JSP页面的JSF应用也采用被JSF技术定义的JSTL 来显示页面上的UI组件和其他对象。

一个简单JSF应用

         这一节描述了不同的开发角色开发一个简单JSF应用的步骤。这些角色包括:
    • 页面设计者,应用JSF标签库创建页面
    • 应用开发者,针对以下内容编写代码,定制转换器,数据验证器,监听器和后台beans
    • 组件开发者,创建定制UI组件
    • 应用架构师,配置应用,包括定义导航规则,配置定制对象,创建部署描述文件

        这个应用很简单,并且不包含任何定制组件。请看12章学习组件编写者的职责。

开发步骤

        开发一个简单JSF应用通常需要完成下列任务:

    • 映射FacesServlet实例
    • 应用UI组件和core tags创建页面
    • 在应用配置资源文件中定义页面导航
    • 开发后台beans.
    • 添加管理的bean声明到应用配置资源文件中
        这一节中的例子是个 guessNumber的应用。它请你猜一个0到10之间的数字。第二个页面告诉你是否猜对了。这个例子会检查你输入的有效性。系统日志打印了Duke's number。

The example used in this section is the guessNumber application, located in the <INSTALL>/javaeetutorial5/examples/web/ directory. It asks you to guess a number between 0 and 10, inclusive. The second page tells you whether you guessed correctly. The example also checks the validity of your input. The system log prints Duke's number. Figure 9-2 shows what the first page looks like.

 

The greeting.jsp page of the guessNumber application

 

Figure 9-2 The greeting.jsp Page of the guessNumber Application

The source for the guessNumber application is located in the <INSTALL>/javaeetutorial5/examples/web/guessNumber/ directory created when you unzip the tutorial bundle (see About the Examples, page xxx).

To build, package, and deploy this example, follow these steps:

    • Go to <INSTALL>/javaeetutorial5/examples/web/guessNumber/.
    • Run ant.
    • Start the Application Server.
    • Run ant deploy.

To learn how to configure the example, refer to the deployment descriptor (the web.xml file), which includes the following configurations:

    •   A display-name element that specifies the name that tools use to identify the application.
    • A servlet element that identifies the FacesServlet instance.
    • A servlet-mapping element that maps FacesServlet to a URL pattern.

To run the example, open the URL http://localhost:8080/guessNumber in a browser.

映射FacesServlet实例

所有的JSF应用必须在部署描述中包含一个指向 FacesServlet实例的映射FacesServlet实例接收请求并将其转入处理周期,并初始化资源。以下部分部署描述文件完成了对 FacesServlet实例的的映射
<servlet>
  <display-name>FacesServlet</display-name>
  <servlet-name>FacesServlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet
  </servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>FacesServlet</servlet-name>
  <url-pattern>/guess/*</url-pattern>
</servlet-mapping>
FacesServlet的映射用一个前缀辨明一个包含JSF组件的JSP页面。正因为这个,这个应用的第一个JSP页面的URL必须包含这个映射。为了达到这个目标,这个应用包括一个包含如下链接的HTML页面:

<a href="guess/greeting.jsp">

  创建页面

创建页面是页面设计者的职责。这个任务涉及页面上的UI组件,映射这些组件到beans,并添加注册了转换器,验证器或监听器的标签到组件上。

在这一节我们会构建这个greeting.jsp页面,及这个应用的第一个页面。就像其他的JSP页面一样,你需要添加通用HTML和HEAD标签:
<HTML xmlns="http://www.w3.org/1999/xhtml"xml:lang="en">
  <HEAD> <title>Hello</title> </HEAD>  
  ...
</HTML>

你还需要页面说明来指定包含内容类型:

<%@ page contentType="application/xhtml+xml" %>
声明标签库

为了在JSP页面中应用JSF组件,你需要在你的页面中访问两个标准标签库,即HTML组件标签库和core标签库声明:

  <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
  <%@ taglib uri="http:.//java.sun.com/jsf/core" prefix="f" %>

第一个标签声明用前缀h声明了HTML组件标签库。所有这个页面中的组件标签都用这个前缀。core标签库声明为f前缀。这个页面中所有的core标签都用这个前缀。

User Interface Component Model includes a table that lists all the component tags included with JavaServer Faces technology. Adding UI Components to a Page Using the HTML Component Tags (page 316) discusses the tags in more detail.


添加视图和表单标签

所有的JSF页面都由组件树代表(represented ),称为视图(view)。view标签代表view的根,所有的JSF组件标签必须在view标签里面,view标签是在core标签里定义的。

form标签代表一个输入表单组件,允许用户输入数据并提交到服务器,通常通过点一个按钮(submit)即可提交。所有的代表可编辑的组件的UI组件标签(比如text field和菜单)必须被嵌入form标签。比如页面greeting.jsp,有些包含在表单中的标签如:outputText, inputText, commandButtonmessage。你可以为form标签指定一个ID。这个ID映射到服务器上相关的form的UI组件。

view标签和form标签添加后,我们的页面看上去就成了这样(最小化了HTML和HEAD标签):

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
  </h:form>
</f:view>
  添加一个Label组件

outputText标签代表一个label。greeting.jsp页有两个outputText标签。一个显示数字0,另一个显示数字10:

  <h:outputText lang="en_US" 
    value="#{UserNumberBean.minimum}"/>
  <h:outputText value="#{UserNumberBean.maximum}"/>

标签的value属性用表达式从UserNumberBean取得mininum和maxinum属性。

添加了outputText标签和一些静态文本之后,greeting页成了现在这个样子::

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
    <h2>Hi. My name is Duke. I'm thinking of a number from
    <h:outputText lang="en_US"
      value="#{UserNumberBean.minimum}"/> to
    <h:outputText value="#{UserNumberBean.maximum}"/>.
    Can you guess it?</h2>
  </h:form>
</f:view>
  添加一个图片
为了在页面上显示一个图片,你需要采用 graphicImage标签。其url属性指定了图片文件的路径。让我们用 graphicImage标签来添加Duke:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
    <h2>Hi. My name is Duke. I'm thinking of a number from
    <h:outputText lang="en_US"
      value="#{UserNumberBean.minimum}"/> to
    <h:outputText value="#{UserNumberBean.maximum}"/>.
    Can you guess it?</h2>
    <h:graphicImage id="waveImg" url="/wave.med.gif" />
  </h:form>
</f:view>
添加Text Field

inputText标签表示文本框组件。在guessNumber例子中,这个文本框取得整型输入值。在greeting.jsp中的这个标签有三个属性:id,label,value。

<h:inputText id="userNo" label="User Number"
    value="#{UserNumberBean.userNumber}">
    ...
</h:inputText>

id属性与由标签表示的组件对象的ID一致。这里,id属性是必须的,因为message标签(用来显示验证错误信息)需要它指向userNo组件。

label属性指定了被错误信息应用的名字来指向这个组件。在这个例子里,label被设置为“User Number”。作为一个例子,如果用户输入23,错误信息就会显示成:

User Number: Validation Error: Value is greater than allowable maximum of 10.

value属性把userNo组件的值和UserNumberBean.userNumber绑定了,UserNumberBean.userNumber保存了用户输入文本框的数据。

添加了inputText 标签后,页面greeting 成了如下样子:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
    <h2>Hi. My name is Duke. I'm thinking of a number from
    <h:outputText lang="en_US"
      value="#{UserNumberBean.minimum}"/> to
    <h:outputText value="#{UserNumberBean.maximum}"/>.
    Can you guess it?</h2>
    <h:graphicImage id="waveImg" url="/wave.med.gif" />
    <h:inputText id="userNo" label="User Number"
      value="#{UserNumberBean.userNumber}">
      ...
    </h:inputText>
  </h:form>
</f:view>

See Backing Beans for more information on creating beans, binding to bean properties, referencing bean methods, and configuring beans.


See Using Text Components (page 321) for more information on the inputText tag.


给文本框注册一个验证器

通过在一个文本框组件标签里面嵌入一个validateLongRange标签,页面设计者就给这个文本框注册了一个LongRangeValidator。这个验证器检查是否这个文本框组件里的数据在一个范围里面,这个范围是由validateLongRange标签的minimummaximum属性定义的。

在greeting页,我们要验证用户输入到文本框的数值。我们在inputText 标签里面添加了一个validateLongRange标签。其maximum和minimum属性用表达式的方式,分别从UserNumberBean获取maximummaximum的属性值,如#{UserNumberBean.minimum} and #{UserNumberBean.maximum}。See Backing Beans for details on value expressions.

在添加了 validateLongRange 标签后,页面如下:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
    <h2>Hi. My name is Duke. I'm thinking of a number from
    <h:outputText lang="en_US"
      value="#{UserNumberBean.minimum}"/> to
    <h:outputText value="#{UserNumberBean.maximum}"/>.
    Can you guess it?</h2>
    <h:graphicImage id="waveImg" url="/wave.med.gif" />
    <h:inputText id="userNo" label="User Number"
      value="#{UserNumberBean.userNumber}">
        <f:validateLongRange
          minimum="#{UserNumberBean.minimum}"
          maximum="#{UserNumberBean.maximum}" />
    </h:inputText>
  </h:form>
</f:view>
For more information on the standard validators included with JavaServer Faces technology, see Using the Standard Validators (page 359).
添加定制信息

当转换或验证失败时,JSF技术提供了标准错误信息来在页面上显示。在部分场景中,你可能需要重载这些标准信息。举个例子,如果一个用户在greeting.jsp的文本框输入了一个字母,他/她就会看到下面的错误信息:

User Number: 'm' must be a number between -2147483648 and 2147483647 Example: 9346

这显然是个错误,因为这个输入框只接受0到10。

为了重载这个信息,你可以在文本框标签中添加一个converterMessage 属性。这个属性引用了你的定制错误信息:

<h:inputText id="userNo" label="User Number" 
    value="#{UserNumberBean.userNumber}"
     converterMessage="#{ErrMsg.userNoConvert}">
...
</h:inputText>

这表明,converterMessage引用了资源ErrMsg中的userNoConvert键值。这个应用架构需要在资源包中定义信息并且配置资源包。See Configuring Error Messages for more information on this.

See Referencing Error Messages (page 348) for more information on referencing error messages.

添加一个按钮

commandButton标签代表常被用于提交输入数据的按钮。这个action属性指明导航机制对下一步往哪个页面导航。 Defining Page Navigation discusses this further.

添加了commandButton 标签后,页面如下:

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
    <h2>Hi. My name is Duke. I'm thinking of a number from
    <h:outputText lang="en_US"
      value="#{UserNumberBean.minimum}"/> to
    <h:outputText value="#{UserNumberBean.maximum}"/>.
    Can you guess it?</h2>
    <h:graphicImage id="waveImg" url="/wave.med.gif" />
    <h:inputText id="userNo" label="User Number"
      value="#{UserNumberBean.userNumber}">
        <f:validateLongRange
          minimum="#{UserNumberBean.minimum}"
          maximum="#{UserNumberBean.maximum}" />
    </h:inputText>
    <h:commandButton id="submit"
      action="success" value="Submit" />
  </h:form>
</f:view>

See Using Command Components for Performing Actions and Navigation (page 327) for more information on the commandButton tag.

显示错误信息
用户提交表单后,当数据转换或验证失败,message 标签常常被用来在页面上显示错误信息。 如果输入亚的数据没有符合 注册在文本框组件的LongRangeValidator的实现定义的规则, greeting.jsp中的 message 标签就会显示错误信息。

在页面上,将message放到哪里,错误信息就会显示在哪里。message标签的style属性允许你指定信息文本的显示风格。它的for属性指向了哪个组件的值验证失败。在这个场景中,userNo组件代表页面中的inputText标签。

我们将 message放到页面最下面:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
  <h:form id="helloForm1">
    <h2>Hi. My name is Duke. I'm thinking of a number from
    <h:outputText lang="en_US"
      value="#{UserNumberBean.minimum}"/> to
    <h:outputText value="#{UserNumberBean.maximum}"/>.
    Can you guess it?</h2>
    <h:graphicImage id="waveImg" url="/wave.med.gif" />
    <h:inputText id="userNo" label="User Number"
      value="#{UserNumberBean.userNumber}"
      converterMessage="#{ErrMsg.userNoConvert}">
      <f:validateLongRange
          minimum="#{UserNumberBean.minimum}"
          maximum="#{UserNumberBean.maximum}" />
    </h:inputText>
    <h:commandButton id="submit"
      action="success" value="Submit" />
    <h:message showSummary="true" showDetail="false"
        style="color: red;
        font-family: 'New Century Schoolbook', serif;
        font-style: oblique;
        text-decoration: overline"
        id="errors1"
        for="userNo"/>
  </h:form>
</f:view>
现在我们完成了greeting页,假如我们也完成了 response.jsp页,我们就可以定义页面导航规则了。

定义页面导航规则

通过定义页面导航,意味着当用户点了一个按钮或者一个超链接,当前页面将往哪个页面流转。在应用配置源文件中配置的这个应用的导航采用了一个强大的基于规则的系统。下面就是一条为guessNumber 定义的导航 规则:

<navigation-rule>
  <from-view-id>/greeting.jsp</from-view-id>
  <navigation-case>
    <from-outcome>success</from-outcome>
    <to-view-id>/response.jsp</to-view-id>
  </navigation-case>
</navigation-rule>
<navigation-rule>
  <from-view-id>/response.jsp</from-view-id>
  <navigation-case>
    <from-outcome>success</from-outcome>
    <to-view-id>/greeting.jsp</to-view-id>
  </navigation-case>
</navigation-rule>

这条导航规则表述了,当
greeting.jsp上的一个按钮被按下并且导航系统被给予一个"success"的逻辑结果时,
应用就会导航到response.jsp。

在这个例子中,逻辑结果在UICommand 组件的action 属性定义:
<h:commandButton id="submit" action="success" 
  value="Submit" />

To learn more about how navigation works, see Navigation Model.

配置错误信息

如果标准错误信息不能切合你的需要,你可以在资源包中创建一个新的错误信息,并在你的应用配置源文件中配置好它。The guessNumber example has one custom converter message, as described in Adding a Custom Message.

下面这条信息存储在资源包中, ApplicationMessages.properties

userNoConvert=The value you entered is not a number.

资源包会在应用配置文件里配置:

<application>
  <resource-bundle>
    <base-name>guessNumber.ApplicationMessages</base-name>
    <var>ErrMsg</var>
  </resource-bundle>
</application>
base-name元素指明资源包的全名。var元素指明页面作者通过表达式语言指向的的名字。下面是 inputText标签:
<h:inputText id="userNo" label="User Number"
  value="#{UserNumberBean.userNumber}"
    converterMessage="#{ErrMsg.userNoConvert}">
    ...
</h:inputText>
converterMessage属性上的表达式引用了 converterMessage在 ErrMsg资源上的键值。

See Registering Custom Error Messages (page 461) for more information on configuring custom error messages.


开发Beans

开发beans是应用开发者的职责。一个典型的JSF应用都用一个后台bean和每个页面挂钩。后台bean定义了和页面上应用的UI组件的属性和方法。

页面作者用组件标签值属性把组件值和bean属性绑定起来。回忆一下 greeting.jsp 上的userNo组件,它就是引用了 UserNumberBeanuserNumber属性:
<h:inputText id="userNo" label="User Number"
      value="#{UserNumberBean.userNumber}">
...
</h:inputText>

这里的userNumber 后台bean映射到userNo组件的数据:
Integer userNumber = null;
...
public void setUserNumber(Integer user_number) {
  userNumber = user_number;
}
public Integer getUserNumber() {
  return userNumber;
}
public String getResponse() {
  if(userNumber != null &&
    userNumber.compareTo(randomInt) == 0) {
      return "Yay! You got it!";
  } else {
    return "Sorry, "+userNumber+" is incorrect.";
  }
}
See Backing Beans for more information on creating backing beans. 

添加受管理的Bean声明

在开发完后台beans后,你需要在应用配置文件里配置它们,这样JSF就可以在需要的时候自动创建这些beans的新的实例。

在应用配置文件里添加受管bean的声明是应用架构师的职责。以下就是 UserNumberBean的受管bean声明:
<managed-bean>
  <managed-bean-name>UserNumberBean</managed-bean-name>
  <managed-bean-class>
    guessNumber.UserNumberBean
  </managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
  <managed-property>
    <property-name>minimum</property-name>
    <property-class>long</property-class>
    <value>0</value>
  </managed-property>
  <managed-property>
    <property-name>maximum</property-name>
    <property-class>long</property-class>
    <value>10</value>
  </managed-property>
</managed-bean>
这个声明配置了 UserNumberBean,它的 minimum属性和 maximum分别被初始化为0和10,并且,当这个bean被创建后,就会被添加到session范围。

页面作者可以用统一表达式语言访问bean的属性,像下面这样:

<h:outputText value="#{UserNumberBean.minimum}"/> 

For more information on configuring beans, see Configuring a Bean.

用户界面组件模型

JSF的UI组件是可配置,可重用的元素,它们构成了JSF应用的用户界面。一个组件可以是简单的,如按钮;或者符合的,如表格,表格由多个组件构成。

JSF技术提供了一个胖的,可伸缩的组件架构,包含如下:
    • 一组UIComponent类,用来指定UI组件的状态和行为
    • 一个持有模型定义了如何用不同方式持有组件
    • 一个时间和监听模型定义如何处理组件事件
    • 一个转换模型定义如何在组件上注册数据转换器
    • 一个验证模型定义如何在组件上注册数据验证器

这一节简短描述了这些组件模型。

用户界面组件类

JSF技术提供了一组UI组件类,与指定了UI组件功能的行为接口关联,这些组件功能包括组件状态,持有对象引用,驱动事件处理和表示一组标准组件。

组件类是完全可扩展,允许组件编写者创建它们自己的定制组件。请看 Chapter 12 ,一个定制图片映射组件的例子。

所有JSF UI组件类都扩展了UIComponentBase类,这个类定义了UI组件的缺省状态和行为。JSF技术包含以下一组UI组件类:

    • UIColumn: 代表UIData 组件中数据的一列
    • UICommand: 代表一个产生actions的控制
    • UIData: 代表绑定到由DataModel组件表示的一组数据
    • UIForm: 包装了一组可以提交数据到服务器的控件。这个组件类似HTML中的form标签
    • UIGraphic: 显示一个图片
    • UIInput: 从用户取得输入数据,这个类是UIOutput的子类
    • UIMessage: 显示本地化的信息
    • UIMessages:显示一组本地化信息
    • UIOutput: 在页面上显示输出数据
    • UIPanel: 管理子组件的布局
    • UIParameter: 代表交互参数
    • UISelectBoolean: 允许用户通过选与反选设置一个布尔值的控件,这个类是UIInput的子类
    • UISelectItem: 代表一组条目中的一个条目
    • UISelectItems: 代表整组条目
    • UISelectMany:允许用户从一组条目中选择多个条目,这个类是 UIInput的子类
    • UISelectOne: 允许用户从一组条目中选择一个条目,这个类是 UIInput的子类
    • UIViewRoot: 代表组件树的根
另外为了扩展 UIComponentBase,组件类可以实现一个或更多的行为接口,每个行为接口都为一组组件定义了确定的行为。

这些行为接口如下:

    • ActionSource: 表明此组件可以产生一个action事件。这个接口意在给基于JSF技术1.1_01或更早版本的组件使用。
    • ActionSource2: 扩展了ActionSource,因此它提供了同样的功能。可是它还允许组件引用处理事件的方法时候用EL。
    • EditableValueHolder: 扩展了ValueHolder,并为可编辑组件详细指定了附加功能,比如验证器和值变化的事件。
    • NamingContainer: 使以此组件为根的所有组件拥有唯一的ID。
    • StateHolder: 指定有状态组件必须在请求间被保存。
    • ValueHolder: 标明维持本地值和在模型层访问数据的选择。
UICommand实现了 ActionSource2StateHolderUIOutput 和继承了实现了 StateHolderValueHolder的组件类都实现了 StateHolder and ValueHolder。 UIInput 和继承了 UIInput的组件类都实现了 EditableValueHolderStateHolderValueHolderUIComponentBase 实现了 StateHolder

See the tJavaServer Faces Technology 1.2 API Specification (http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/javax/faces/component/package-summary.html) for more information on these interfaces.

只有组件编写者才需要直接使用组件类和行为接口。页面作者和应用开发者只需要通过在页面上包含标签来使用标准UI组件。举个例子,UICommand 能由一个按钮或超链接持有。


下一节解释了持有模型如何工作,页面作者如何通过选择合适的标签来持有组件。

组件持有模型

JSF组件架构设计成组件功能由组件列定制,组件持有能被分开的持有者定义。这样设计有几个好处,包括:
    • 组件编写者可以在只定义一次组件行为的情况下创建多个持有者,每个持有者定义了不同的方式来针对同一或不同的客户端持有组件
    • 页面作者和应用开发者能通过选择组件和持有者的合适组合来改变页面上的组件显示。

render kit 定义了如何将组件类映射到适宜特殊客户端的组件标签。JSF实现包含了标准HTMLrender kit来render一个HTML客户端。

The render kit defines a set of Renderer classes for each component that it supports. Each Renderer class defines a different way to render the particular component to the output defined by the render kit. For example, a UISelectOne component has three different renderers. One of them renders the component as a set of radio buttons. Another renders the component as a combo box. The third one renders the component as a list box.

Each JSP custom tag defined in the standard HTML render kit is composed of the component functionality (defined in the UIComponent class) and the rendering attributes (defined by the Renderer class). For example, the two tags in Table 9-1 represent a UICommand component rendered in two different ways.

Table 9-1 UICommand Tags 
Tag
Rendered As
commandButton

 

Login Button

 

commandLink

 

A Hyperlink

 

 

The command part of the tags shown in Table 9-1 corresponds to the UICommand class, specifying the functionality, which is to fire an action. The button and hyperlink parts of the tags each correspond to a separate Renderer class, which defines how the component appears on the page.

The JavaServer Faces implementation provides a custom tag library for rendering components in HTML. It supports all the component tags listed in Table 9-2. To learn how to use the tags in an example, see Adding UI Components to a Page Using the HTML Component Tags (page 316).

Table 9-2 The UI Component Tags 
Tag
Functions
Rendered As
Appearance
column
Represents a column of data in a UIData component.
A column of data in an HTML table
A column in a table
commandButton
Submits a form to the application.
An HTML
<input type= type >
element, where the type value can be submit, reset, or image
A button
commandLink
Links to another page or location on a page.
An HTML <a href> element
A hyperlink
dataTable
Represents a data wrapper.
An HTML <table> element
A table that can be updated dynamically
form
Represents an input form. The inner tags of the form receive the data that will be submitted with the form.
An HTML <form>
element
No appearance
graphicImage
Displays an image.
An HTML <img>
element
An image
inputHidden
Allows a page author to include a hidden variable in a page.
An HTML
<input type=hidden> element
No appearance
inputSecret
Allows a user to input a string without the actual string appearing in the field.
An HTML <input type=password> element
A text field, which displays a row of characters instead of the actual string entered
inputText
Allows a user to input a string.
An HTML <input type=text> element
A text field
inputTextarea
Allows a user to enter a multiline string.
An HTML <textarea> element
A multirow text field
message
Displays a localized message.
An HTML <span> tag if styles are used
A text string
messages
Displays localized messages.
A set of HTML <span> tags if styles are used
A text string
outputFormat
Displays a localized message.
Plain text
Plain text
outputLabel
Displays a nested component as a label for a specified input field.
An
HTML <label> element
Plain text
outputLink
Links to another page or location on a page without generating an action event.
An HTML <a> element
A hyperlink
outputText
Displays a line of text.
Plain text
Plain text
panelGrid
Displays a table.
An HTML <table> element with <tr> and <td> elements
A table
panelGroup
Groups a set of components under one parent.
 
A row in a table
selectBoolean
Checkbox
 
Allows a user to change the value of a Boolean choice.
An HTML <input type=checkbox> element.
A checkbox
selectItem
 
Represents one item in a list of items in a UISelectOne component.
An HTML <option> element
No appearance
selectItems
Represents a list of items in a UISelectOne component.
A list of HTML <option> elements
No appearance
selectMany
Checkbox
Displays a set of checkboxes from which the user can select multiple values.
A set of HTML <input> elements of type checkbox
A set of checkboxes
selectMany
Listbox
Allows a user to select multiple items from a set of items, all displayed at once.
An HTML <select> element
A list box
selectManyMenu
Allows a user to select multiple items from a set of items.
An HTML <select> element
A scrollable combo box
selectOne
Listbox
Allows a user to select one item from a set of items, all displayed at once.
An HTML <select> element
 
A list box
selectOneMenu
Allows a user to select one item from a set of items.
An HTML <select> element
A scrollable combo box
selectOneRadio
Allows a user to select one item from a set of items.
An HTML <input type=radio> element
A set of radio buttons

 

转换器模型

一个JSF模型能有选择地把组件和服务器端数据关联起来。这个对象就是一个JavaBeans组件,比如后台bean。一个应用可以gets和sets这个对象的数据。

当一个组件绑定倒一个对象,这个应用就拥有了这个组件数据的两个视图:

    • 模型视图,其中的数据代表数据类型,比如int 或者long
    • 一般视图,其中的数据代表通用数据,可以被用户读写。举个例子,一个java.util.Date可能代表一个格式为mm/dd/yy 的文本字符串或者一组3个文本字符串

当bean属性和组件被组件数据支持的数据类型关联时,JSF在这两种视图间自动转换组件数据。举个例子,如果一个UISelectBoolean组件和java.lang.Boolean类型的bean属性关联,JSF实现会自动转换组件数据,即从String转换为Boolean。另外,一些组件数据必须绑定倒特殊类型。例如,一个UISelectBoolean数据必须绑定到booleanjava.lang.Boolean。

有时候你可能需要将组件数据转化成非标准类型,或者你可能需要转换数据的格式。为了简化这个,JSF技术允许你在 UIOutput 组件或这个组件的子组件上注册转换器实现。如果你在一个组件上这测了转换器实现,这个转换器实现就会在两个视图直接转换组件数据。

你也可以用JSF实现支持的标准转换器或者创建你自己的定制转换器。

在应用中创建自定义转换器,有三件事必须做:


事件和监听器模型

JSF事件和监听器模型类似JavaBeans事件模型,它有应用可以用来处理UI组件产生的事件的强类型的事件类和接口。

 

An Event object identifies the component that generated the event and stores information about the event. To be notified of an event, an application must provide an implementation of the Listener class and must register it on the component that generates the event. When the user activates a component, such as by clicking a button, an event is fired. This causes the JavaServer Faces implementation to invoke the listener method that processes the event.

JavaServer Faces technology supports three kinds of events: value-change events, action events, and data-model events.

An action event occurs when the user activates a component that implements ActionSource. These components include buttons and hyperlinks.

A value-change event occurs when the user changes the value of a component represented by UIInput or one of its subclasses. An example is selecting a checkbox, an action that results in the component's value changing to true. The component types that can generate these types of events are the UIInput, UISelectOne, UISelectMany, and UISelectBoolean components. Value-change events are fired only if no validation errors were detected.

Depending on the value of the immediate property (see The immediate Attribute, page 318) of the component emitting the event, action events can be processed during the invoke application phase or the apply request values phase, and value-change events can be processed during the process validations phase or the apply request values phase.

A data-model event occurs when a new row of a UIData component is selected. The discussion of data-model events is an advanced topic. It is not covered in this tutorial but may be discussed in future versions of this tutorial.

There are two ways to cause your application to react to action events or value-change events emitted by a standard component:

    • Implement an event listener class to handle the event and register the listener on the component by nesting either a valueChangeListener tag or an actionListener tag inside the component tag.
    • Implement a method of a backing bean to handle the event and refer to the method with a method expression from the appropriate attribute of the component's tag.

See Implementing an Event Listener (page 398) for information on how to implement an event listener. See Registering Listeners on Components (page 356) for information on how to register the listener on a component.

See Writing a Method to Handle an Action Event (page 411) and Writing a Method to Handle a Value-Change Event (page 413) for information on how to implement backing bean methods that handle these events.

See Referencing a Backing Bean Method (page 369) for information on how to refer to the backing bean method from the component tag.

When emitting events from custom components, you must implement the appropriate Event class and manually queue the event on the component in addition to implementing an event listener class or a backing bean method that handles the event. Handling Events for Custom Components (page 439) explains how to do this.

Validation Model 数据验证模型

JSF技术支持验证如文本框的本地数据的机制。这种验证发生在反应模型数据和本地值更新之前。

JavaServer Faces technology supports a mechanism for validating the local data of editable components (such as text fields). This validation occurs before the corresponding model data is updated to match the local value.

就像数据转换模型,数据验证模型定义了一组标准类来完成通用的数据检验。JSF核心标签库定义了一组标签为标准验证器实现负责。

Like the conversion model, the validation model defines a set of standard classes for performing common data validation checks. The JavaServer Faces core tag library also defines a set of tags that correspond to the standard Validator implementations. See Table 10-7 for a list of all the standard validation classes and corresponding tags.

Most of the tags have a set of attributes for configuring the validator's properties, such as the minimum and maximum allowable values for the component's data. The page author registers the validator on a component by nesting the validator's tag within the component's tag.

The validation model also allows you to create your own custom validator and corresponding tag to perform custom validation. The validation model provides two ways to implement custom validation:

If you are implementing a Validator interface, you must also:

If you are implementing a backing bean method to perform validation, you also must reference the validator from the component tag's validator attribute. See Referencing a Method That Performs Validation (page 372) for more information.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值