JSF简单介绍


一、 什么是 JSF:


JavaServer Faces (JSF) 是一种用于构建 Web 应用程序的新标准 Java 框架。它提供了一种以组件为中心来开发 Java Web 用户界面的方法,从而简化了开发。


JavaServer Faces于2004年三月1.0版正式提出,清楚的将Web应用程序的开发者划分了三个角色:网页设计人员、应用程序设计人员以及UI组件开发者。 从使用的角度来看,网页设计人员与应用程序设计人员能够他们所熟悉的方式开发程序,而不用侵入彼此的工作范围,而UI组件开发者能够独立的开发个别组件,细节的部份留给了他们来处理。


JSF 还通过将良好构建的模型-视图-控制器 (MVC) 设计模式集成到它的体系结构中,确保了应用程序具有更高的可维护性。


因为 JSF 是通过 Java Community Process (JCP) 开发的一种 Java 标准,因此开发工具供应商全然可以为 JavaServer Faces 提供易于使用的、高效的可视化开发环境。


 


二、 JSF 体系结构:


JSF 的主要优势之中的一个就是它既是 Java Web 应用程序的用户界面标准又是严格遵循模型-视图-控制器 (MVC) 设计模式的框架。用户界面代码(视图)与应用程序数据和逻辑(模型)的清晰分离使 JSF 应用程序更易于管理。为了准备提供页面相应用程序数据訪问的 JSF 上下文和防止对页面未授权或不对的訪问,全部与应用程序的用户交互均由一个前端FacesServlet(控制器)来处理。



三、 JSF 生命周期:


FacesServlet 充当用户和 JSF 应用程序之间的纽带。它在明白限定的 JSF 生命周期(规定了用户请求之间的整个事件流)的范围内工作。


1.   当JSF页面上的一个事件发生时(比方:用户单击了一个button),事件通知通过HTTP发往server。server端使用FacesServet这个特殊的Servlet处理该通知。


2.   FacesServlet一接收到用户的请求就创建一个FacesContext对象(JSF上下文,它存放了应用程序的全部数据)。在处理过程中,主要改动的就是这个FaceContext对象。


3.   接着就是处理过程,处理器是一个叫作Lifecycle的对象。FacesServet把控制权转交给Lifecycle对象。该对象分6个阶段来处理FacesContext对象以生成响应,最后将响应发回client。


Lifecycle对象处理JSP请求所须要的一系列动作称为请求处理生命周期。




因为请求处理生命周期里的应用请求值、处理验证、更新模型值和调用应用程序等阶段都能够在当前的请求相应的FacesContext实例中加入�事件,因此,JSF实现必须在这些阶段后处理这些事件。


 



阶段



说明



恢复视图



为选定的视图找到或创建组件树。


一旦用户单击JSP页面上的链接或button,就会启动此阶段。JSF应用里的JSP页面被表示成一个组件树。JSF实现会进一步将这些组件链接到事件处理程序和验证程序,并将视图保存在FacesContext对象中,以备后面的处理过程所用。FacesContext对象包括了JSF用来管理当前会话中当前请求的GUI组件状态所须要的全部状态信息。



应用请求值



使用请求中发送来的值来更新组件树的组件值。由于请求中发送来的值都是String类型的,所以在更新组件树的组件值之前,必须将这些值转换为对应类型。这个过程也是解码。若转换有错误,这些错误将加入�到FacesContext对象。



处理验证



当每一个组件的本地值被更新后,Lifecycle对象都会依据这些注冊组件的验证规则来验证这些值的合法性。


假设输入的值不符合验证规则,就会将验证错误加入�至FacesContext对象,并将组件标记为无效。JSF将转至呈现响应阶段,并显示带有验证错误消息的视图。


假设没有遇到验证错误,JSF将进入下一阶段。



更新模型值



更新与组件相关的后台bean(也叫管理bean)或者模型对象的值。仅仅有那些与组件值绑定在一起的Bean属性才会被更新。



调用应用程序



JSF控制器调用应用程序来处理应用程序级的事件,如提交一个表单。(此阶段可运行业务逻辑)



呈现响应



使用当前的显示技术(如JSP)显示选定的视图。



 


四、 设置JSF环境:


1.    JSF库:


您能够到JSF官方站点的下载区下载其压缩包 :http://java.sun.com/javaee/javaserverfaces/download.html,在下载压缩包并解压缩之后,将其lib文件夹下的jar 档案复制至您的Web应用程序的/WEB-INF/lib文件夹下,另外您还须要jstl.jar与standard.jar 文件,这些文件您能够在sample 文件夹下,解压缩其中的一个范例,在它的/WEB-INF/lib文件夹下找到,将之中的一个并复制至您的Web应用程序的/WEB-INF/lib文件夹下。


您总共须要下面的jar文件:


1)   jsf-api.jar :定义于JSF规范中的JSF API类。


2)   jsf-impl.jar :特定实现的JSF类(不同的实现组织,包名可能不同)。


3)   rcommons-digester.jar :解析xml文件的类。


4)   commons-collections.jar :提供了基于Java Collection类创建的各种类。


5)   commons-beanutils.jar :定义和訪问JavaBean组件属性的应用工具。


6)   commons-logging.jar :日志工具。


7)   jstl.jar :JSTL API类。


8)   standard.jar :JSTL 的实现类。


2.    配置:


对全部Java web应用来说,配置開始于Web应用部署描写叙述符。另外,Faces具有自己的扩展配置系统以支持各种附加特征。


1)   Servlet配置:


JSF应用须要Servlet,称为FacesSevlet。它是整个应用的前端控制器。全部的请求都通过FacesServlet来处理:



<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns="http://java.sun.com/xml/ns/j2ee"


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">


 <display-name>guessNumber</display-name>


 <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>


</web-app>



在上面的定义中,我们将全部.faces的请求交由FaceServlet来处理,FaceServlet会唤起相对的.jsp网页,比如请求是/index.faces的话,则实际上会唤起/index.jsp网页,完毕以上的配置,您就能够開始使用JSF了。


2)   JSF应用配置:


       JSF的应用配置文件提供了对整个应用的相关信息的“地图”,它处理诸如导航规则、受管Bean、国际化等。这个文件就放置在应用程序的WEB-INF文件夹下。


 


五、 演示样例及分析:


演示样例要求:要求用户猜一个0到10之间的数字,第二页告诉用户猜的是否正确,要求检查用户输入的合法性。


步骤:


1.    创建一名为guessNumber的web应用程序。按“设置JSF环境”准备好JSF库。


2.    创建受管Bean(或叫后台Bean):



package chapter5;


 


import java.util.Random;


 


public class UserNumberBean {


    /** 用户输入的数字 */


    private int userNumber = 0;


    /** 正确答案数字 */


    private int keyNumber = 0;


    /** 最小值 */


    private int minNum = 0;


    /** 最大值 */


    private int maxNum = 10;


    /** 回应客户的信息字符串 */


    private String responseStr;


   


    public UserNumberBean() {


         Random random = new Random();


         keyNumber = random.nextInt(10);


         System.out.println("正确数字是:" + keyNumber);


    }


 


    public int getUserNumber() {


        return userNumber;


    }


 


    public int getKeyNumber() {


        return keyNumber;


    }


 


    public int getMaxNum() {


        return maxNum;


    }


 


    public int getMinNum() {


        return minNum;


    }


 


    public String getResponseStr() {


        if(userNumber == keyNumber){


            return "您真聪明,您猜对了!";


        }else{


            return "对不起,您猜错了!不是"+ userNumber +"!";


        }


    }


 


    public void setUserNumber(int userNumber) {


        this.userNumber = userNumber;


    }


 


    public void setKeyNumber(int keyNumber) {


        this.keyNumber = keyNumber;


    }


 


    public void setMaxNum(int maxNum) {


        this.maxNum = maxNum;


    }


 


    public void setMinNum(int minNum) {


        this.minNum = minNum;


    }


 


    public void setResponseStr(String responseStr) {


        this.responseStr = responseStr;


    }


}



受管Bean充当控制器的角色:通常它包括想要从用户处收集的属性,以及处理这些属性、操纵UI和运行其它一些应用处理的监听器方法。即它接收用户提交的数据,然后调用对应的模型的业务方法来处理用户的请求。


3.    在JSF的配置文件faces-config.xml(该文件放置在WEB-INF下)中配置受管理的后台Bean:



<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE faces-config PUBLIC


"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"


"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">


<faces-config xmlns="http://java.sun.com/JSF/Configuration">


 


<managed-bean>


    <managed-bean-name​​[q1]​​ >UserNumberBean</managed-bean-name>


 <managed-bean-class​​[q2]​​ >chapter5.UserNumberBean</managed-bean-class>


    <managed-bean-scope​​[q3]​​ >session</managed-bean-scope>


 </managed-bean>


</faces-config>



 


4.    开发基于JSF的用户界面:


建立JSP页面,使用定制标签表示将作为HTML元素用的JSF组件。


第一个页面:猜数页面guess.jsp:



<%@ page contentType="text/html; charset=GBK" %>


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


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


<html>


<head>


<title>猜数字</title>


</head>


<body bgcolor="#ffffff">


<f:view>


 <h:form id="helloForm">


    <h2>请猜一个<h:outputText value="#{UserNumberBean.minNum}" />


    至<h:outputText value="#{UserNumberBean.maxNum}" />的数字</h2>


 


<h:inputText id="userNo"


 value="#{UserNumberBean.userNumber}">


     <f:validateLongRange minimum="#{UserNumberBean.minNum}"


 maximum="#{UserNumberBean.maxNum}" />


    </h:inputText>


   


<h:commandButton id="submit" action="success" value="提交" />


<br/>


 


    <h:message style="color:red;" id="errors1" for="userNo"/>


 </h:form>


</f:view>


</body>


</html>



第二个页面:结果页面response.jsp:



<%@ page contentType="text/html; charset=GBK" %>


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


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


<html>


<head>


<title>结果</title>


</head>


<body bgcolor="#ffffff">


<f:view>


 <h:form id="responseForm">


    <h2>


     <h:outputText id="result" value="#{UserNumberBean.responseStr}" />


    </h2>


    


    <h:commandButton id="back" value="返回" action="success" />


 </h:form>


</f:view>


</body>


</html>



 


5.    编写事件监听器或者导航规则:


l 编写事件监听器来决定事件发生时应该有的反应。比方用户单击一个button或提交了表单。假设没有事件监听器,在这一步定义页面导航规则。


l 导航规则涉及到定义应用程序中各种页面的跳转。


本例是配置导航规则:在faces-config.xml文件里:



<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">


<faces-config xmlns="http://java.sun.com/JSF/Configuration">


 <managed-bean>


    <managed-bean-name>UserNumberBean</managed-bean-name>


   <managed-bean-class>chapter5.UserNumberBean</managed-bean-class>


    <managed-bean-scope>session</managed-bean-scope>


 </managed-bean>


 


<navigation-rule>


    <from-view-id​​[q4]​​ >/guess.jsp</from-view-id>


    <navigation-case​​[q5]​​ >


      <from-outcome​​[q6]​​ >success</from-outcome>


      <to-view-id​​[q7]​​ >/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>/guess.jsp</to-view-id>


    </navigation-case>


 </navigation-rule>


</faces-config>



第一个导航规则能够这样理解:从guess.jsp页面出发有个导航规则,它有一个导航案例:就是当结果为“successs”时导航到response.jsp。


注:在导航时,预设都是使用forward的方式,您能够在<navigation-case>中添�一个<redirect/>子元素,让JSF发送HTTP重定向到新的视图。


6.    部署、执行、调试


六、 JSF的用户界面组件模型:


JavaServer Faces 的真正威力在于它的用户界面组件模型。在该模型中,应用程序全然用组件集合构建,这些组件能够针对多种client类型用不同的方式来进行显示。


JSF的用户界面组件模型由UI组件类、显示模型、事件模型、数据置换模型以及数据验证模型组成。


1.   UI组件类:与其它专有技术(如 ASP.Net)有点相似,JSF 的 UI 组件模型技术使开发者能够使用预先构建的用户界面 (UI) 组件来构建 Web 用户界面(而非全然从头构建用户界面),从而提供了前所未有的开发效率。JSF UI 组件有多种形式,能够简单到仅仅是显示文本的 outputLabel,或者复杂到能够表示来自数据集合(如数据库表)的表格化数据的 dataTable。


JavaServer Faces 规范在其參考实施中提供了一组基本 UI 组件,这些组件本身是很实用的。它们包含两个组件库:


l “HTML”组件库 — 它大部分映射了标准的 HTML 输入元素。


l “Core”组件库 — 它辅助常见的应用程序开发任务(如,国际化和验证/转换输入数据)。


假设在JSP页面中使用HTML和Core组件库,必须在JSP页面中包括下列的taglib指令。



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


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



 


除了提供一个基本 UI 组件库之外,JSF API 还提供了扩展和创建定制 JSF UI 组件的功能,从而在基本组件之上提供很多其它功能。


 


2.   组件显示模型:组件的功能通常环绕着两个动作:解码和编码数据。解码是把进入的请求參数转换成组件的值的过程。编码是把组件的当前值转换成相应的标签(也就是HTML)的过程。


组件显示功能有两种工作实现方式:


l 直接实现:组件自己实现解码和编码。


l 托付实现:组件托付呈现器进行解码和编码。


3.   数据转换模型:提供了各和类和接口,使JSF页面中的文本数据可以转换成原始数据类型。将数据从视图到模型和从模型到视图的全部转换都是由转换模型处理的。


4.   事件和监听器模型:JSF实现由事件和监听器类组成。每当JSF组件激发事件时,就会创建一个事件对象(事件对象包括的信息有页面中哪个组件生成了事件等),而后JSF将调用对应监听器的方法来捕获事件。由JSF组件激发的两个最常见事件是动作事件和值更改事件。


动作事件在组件(button和链接)被激活时触发。当用户更改组件(如复选框)的值时将激发值更改事件。


要使组件可以响应动作事件或值更改事件。应用程序可以使用下面技术之中的一个:


3)   实现事件监听器类以处理事件和在组件上注冊事件:


4)   在后台Bean的方法中实现事件处理,并在组件的方法绑定表达式中引用此方法。


5.   验证模型:JSF提供了各种类来验证在JSF页面上各个控件中包括的数据。此验证在更新模型中的数据之前进行。使用这些标签进行的验证包括:检查字段中文本的长度和检查字段值是否在指定的范围内等。JSF提供了三种内建验证器,即:<f:validateDoubleRange>、<f:validateLongRange>、<f:validateLength>。使用这些验证器的方法是将它们嵌入到组件标签内,代码例如以下所看到的:



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


   <f:validateLongRange minimum="#{UserNumberBean.minNum}"


maximum="#{UserNumberBean.maxNum}" />


</h:inputText>



这段代码要求userNo文本字段中所输入的值要在指定的最小值和最大值之间。