1、JSF中的3大主导器件,有的从程序设计人士的角度来消除

JSF提供了汪洋的UI标签来简化创造视图。这一个UI标签类似于ASP.NET中的服务器组件。使用那个标签,能够因此其value,binding,action,actionListener等性能直接绑定到托管Bean的属性,实例或然措施上。

1. JSF入门

藉由以下的多少个主旨,能够大要明白JSF的概貌与特色,大家来探视网页设计人士与应用程序设计职员各负担什么。

一、JSF中的叁大亚湾原子核能发电站心组件:

1.1简介JSF

Web应用程序的开支与观念的单机程序支付在本质上设有着太多的反差,Web应用程序开辟职员于今不可防止的必须处理
HTTP的细节,而HTTP无状态的
(stateless)本质,与历史观应用程序必须保险程序运维进程中的音讯有拨云见日的背离,再则Web应用程序面对网址上不相同的使用者同时的存取,其施行绪
安全主题材料以及资料证实、调换处理等难题,又是错综复杂且难以消除的。

单向,本质上是静态的HTML与精神上是动态的应用程序又是壹项违背,那造成不可转败为胜的,处理网页设计的雕塑人士与
程序设计职员,必须被互相参与至视图组件中的逻辑相互困扰,尽管某个视图显示逻辑以卷标的点子展现,试图呈现对网页设计图案职员的亲切,但它终归必须牵涉
到有关的流程逻辑。

有这几个方案试着化解各样的窘况,而个别的视角各区别,有的从程序设计人士的角度来缓解,有的从网页设计职员的角度来
化解,各类的框架被提议,所产生的是各个不统一的价签与框架,为了促进生产本事的咬合开辟环境(IDE)难以结成那个标签与框架,另1方面,开荒职员的学习负
担也不绝于耳的加剧,他们不能够不1人掌握四个角色的干活。

Java Server
Faces的建议在准备缓解这些主题材料,它试图在差异的角度上提供网页设计人士、应用程序设计人士、组件开采职员消除方案,让分歧手艺的人手能够相互合作又
不相互干扰,它归纳了各家厂家现存的本事特色,由Java Community
Process(JCP)团队研拟出来的1套标准,并在200四年7月刊载了Java
ServerFaces 一.0实作成果。

从网页设计职员的角度来看,Java Server
Faces提供了一套像是新本子的HTML标签,但它不是静态的,而是动态的,能够与后端的动态程序结合,但网页设计人士不需求理会后端的动态部份,网页
设计人士甚至不太供给接触JSTL那类的卷标,也足以动态的彰显数据(像是动态的询问表格内容),Java
Server
Faces提供标准的价签,那能够与网页编辑程序结合在协同,另一方面,Java
Server Faces也同意你自订标签。

从应用程序设计职员的角度来看,Java Server
Faces提供三个与观念应用程序开垦相近似的模子(当然因某个本质上的异样,模型依然稍有两样),他们得以依据事件驱动来开垦顺序,不必关注HTTP的
处理细节,假若必须处理部分视觉组件的性质的话,他们也得以一向在结合开辟环境上拖拉这个零部件,点选设定组件的天性,Java
Server
Faces甚至还为应用程序设计职员处理了对象与字符串(HTTP传送本质上正是字符串)间不相配的转变难点。

从UI组件开采职员的角度来看,他们得以安顿通用的UI组件,让应用程序的支付生产技术巩固,就像是同在规划Swing组件等,UI开辟人士能够独立开垦,只要定义好不毫不相关系的质量选项来调整细节,而不要十分受网页设计职员或应用程序设计人士的纷扰。

两个角色的学问领域标准上得以互不困扰,依据你的剧中人物,您假如通晓个中贰个文化领域,就足以运用Java
Server Faces,别的剧中人物的知识领域您能够不要通晓太多细节。

本来,就个中三个角色单独来看,Java Server
Faces隐藏了过多细节,若要全盘驾驭,其实Java Server
Faces是错综复杂的,每贰个拍卖的条件都值得深刻钻探,所以读书Java
ServerFaces时,您要采取的是周到驾驭,依然从利用的角度来打听,那就决定了你学习时所要费用的心血。

要选取JSF,首先你要先得到Java Server Faces参考实作(Java Server Faces
Reference
Implementation),在将来,JSF会与Container整合在同步,届时你假使下载协理的Container,就能够使用JSF的成效。

请至 JSF
官方网站的下载区
载参考实作,在下载压缩档并解压缩之后,将其 lib 目录下的 jar
档案复制至您的Web应用程序的/WEB-INF/lib目录下,别的您还亟需 jstl.jar 与
standard.jar
档案,这个档案您能够在sample目录下,解压缩个中的1个范例,在它的/WEB-INF/lib目录下找到,将之壹并复制至您的Web应用程序的
/WEB-INF/lib目录下,您一同必要以下的档案:

* jsf-impl.jar

    *jsf-api.jar

    *commons-digester.jar

    *commons-collections.jar

    *commons-beanutils.jar

    *jstl.jar

* standard.jar

接下去配置Web应用程序的web.xml,使用JSF时,全体的伏乞都由此Faces
Servlet来拍卖,您能够如下概念:

 

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

 

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

 

    <description>

        JSF Demo

</description>

 

<display-name>JSF Demo</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>

 

    <welcome-file-list>

        <welcome-file>index.html</welcome-file>

</welcome-file-list>

 

 </web-app>

在上头的概念中,大家将全部.faces的央求交由FaceServlet来拍卖,FaceServlet会唤起相对的.jsp网页,例如请求是/index.faces的话,则实际上会唤起/index.jsp网页,达成上述的配备,您就能够起来运用JSF了。

a、 JSF容器管理的托管Bean
b、 JSF提供的UI标签,应用分界面包车型客车UI标签直接绑定到托管Bean
c、 页面导航规则

1.2第一个JSF程序

明日得以付出二个粗略的顺序了,大家将筹划一个回顾的登录程序,使用者送盛名称,之后由程序显示使用者名称及迎接新闻。

 

先后开垦职员

先看看应用程序开垦人士要作些什么事,大家创作2个简易的JavaBean:

UserBean.java

package onlyfun.caterpillar;

 

public class UserBean

{

 

    private String name;

 

public void setName(String name)

{

        this.name = name;

    }

 

public String getName()

{

        return name;

    }

}

其1Bean将积存使用者的称呼,编写翻译好未来放置在/WEB-INF/classes下。接下来设计页面流程,大家将先
呈现一个登陆网页/pages/index.jsp,使用者填入名称并送出窗体,之后在/pages/welcome.jsp中显得Bean中的使用者名
称与欢迎音信。为了让JSF知道大家所设计的Bean以及页面流程,大家定义1个/WEB-INF/faces-config.xml:

faces-config.xml

<?xml version="1.0"?>

 <!DOCTYPE faces-config PUBLIC

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

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

 

 <faces-config>

    <navigation-rule>

        <from-view-id>/pages/index.jsp</from-view-id>

        <navigation-case>

            <from-outcome>login</from-outcome>

            <to-view-id>/pages/welcome.jsp</to-view-id>

        </navigation-case>

    </navigation-rule>

 

    <managed-bean>

        <managed-bean-name>user</managed-bean-name>

         <managed-bean-class>

             onlyfun.caterpillar.UserBean

         </managed-bean-class>

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

    </managed-bean>

 </faces-config>

在<navigation-rule>中,我们定义了页面流程,当呼吁来自<from-view-
id>中钦赐的页面,并且钦点了<navigation-case>中的<from-outcome>为login时,则
会将呼吁导向至<to-view-id>所钦点的页面。在<managed-bean>中我们能够统1管理咱们的Bean,大家设定Bean对象的水土保持范围是session,也等于使用者开启浏览器与程序互动进程中都现成。接下来要告知网页设计职员的新闻是,他们能够应用的
Bean名称,即<managed-bean-name>中设定的称呼,以及地点所定义的页面流程。

网页设计人士

首先网页设计人士撰写index.jsp网页:

index.jsp

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

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

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

<html>

 <head>

 <title>第一个JSF程序</title>

 </head>

<body>

    <f:view>

        <h:form>

            <h3>请输入您的名称</h3>

            名称: <h:inputText value="#{user.name}"/><p>

            <h:commandButton value="送出" action="login"/>

        </h:form>

    </f:view>

 </body>

</html>

大家利用了JSF的core与html标签库,core是关于于UI组件的处理,而html则是有关于HTML的进阶标签。<f:view>与<html>有左近的意义,当你要发轫使用JSF组件时,那几个零件一定要在<f:
view>与</f:view>之
间,就犹如使用HTML时,全体的竹签一定要在<html>与<
/html>之间。html卷标库中差不离都以与HTML卷标相关的进阶卷标,<h:form>会发出2个窗体,大家使用<h:
inputText>来展现user那一个Bean对象的name属性,而<h:commandButton>会发生贰个交付开关,我们在action属性中内定将依照此前定义的login页面流程中前往welcome.jsp页面。网页设计人士不必理会窗体传送之后要作些什么,他借使设
计好欢迎页面就好了:

welcome.jsp

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

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

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

 <html>

 <head>

 <title>第一个JSF程序</title>

 </head>

 <body>

    <f:view>

        <h:outputText value="#{user.name}"/> 您好!

        <h3>欢迎使用 Java Server Faces!</h3>

    </f:view>

 </body>

 </html>

这么些页面没什么供给表明的了,如您所见到的,在网页上从不程序逻辑,网页设计人士所作的便是依照页面流程,使用有关称号
抽取多少,而不用担忧其实程序是什么运作的。接下来运转Container,连接上你的应用程序网站,例
如:http://localhost:8080/jsfDemo/pages/index.faces,填入名称并送出窗体,您的欢迎页面就会显示了。

下面大家就来介绍UI标签:

一.三简约的导航 Navigation

在首先个JSF程序中,我们简要的定义了页面包车型客车流水生产线由index.jsp 到
welcome.jsp,接下去我们扩张程序,让它能够依照使用者输入的名称与密码是或不是科学,决定要出示欢迎新闻或是将使用者送回原页面进行再度登陆。首先大家修改一下UserBean:

 

UserBean.java

package onlyfun.caterpillar;

 

public class UserBean

{

 

    private String name;

    private String password;

    private String errMessage;

 

public void setName(String name)

{

        this.name = name;

    }

 

public String getName()

{

        return name;

    }

 

public void setPassword(String password)

{

        this.password = password;

    }

 

public String getPassword()

{

        return password;

    }

 

public void setErrMessage(String errMessage)

{

        this.errMessage = errMessage;

    }

 

public String getErrMessage()

{

        return errMessage;

    }

 

public String verify()

{

        if(!name.equals("justin") ||!password.equals("123456"))

              {

            errMessage = "名称或密码错误";

            return "failure";

        }

        else

              {

            return "success";

        }

    }

 }

在UserBean中,我们扩张了密码与错误音讯属性,在verify()方法中,大家检查使用者名称与密码,它传到2个字符串,”failure”表示登陆错误,并会设定错误信息,而”success”表示登录正确,这几个流传的字符串将调整页面包车型客车流水生产线。接下来大家修改一
下faces-config.xml 中的页面流程定义:

faces-config.xml

<?xml version="1.0"?>

 <!DOCTYPE faces-config PUBLIC

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

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

 

 <faces-config>

    <navigation-rule>

        <from-view-id>/pages/index.jsp</from-view-id>

        <navigation-case>

            <from-outcome>success</from-outcome>

            <to-view-id>/pages/welcome.jsp</to-view-id>

        </navigation-case>

        <navigation-case>

            <from-outcome>failure</from-outcome>

            <to-view-id>/pages/index.jsp</to-view-id>

        </navigation-case>

    </navigation-rule>

 

    <managed-bean>

        <managed-bean-name>user</managed-bean-name>

        <managed-bean-class>

            onlyfun.caterpillar.UserBean

        </managed-bean-class>

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

    </managed-bean>

 </faces-config>

 

遵照地点的定义,当传回的字符串是”success”时,将前去
welcome.jsp,如若是”failure”的话,将送回
index.jsp。接下来告诉网页设计人士Bean名称与连锁属性,以及调整页面流程的verify名称,咱们修改
index.jsp 如下:

index.jsp

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

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

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

 <html>

 <head>

 <title>第一个JSF程序</title>

 </head>

 <body>

    <f:view>

        <h:form>

            <h3>请输入您的名称</h3>

            <h:outputText value="#{user.errMessage}"/><p>

           名称: <h:inputText value="#{user.name}"/><p>

           密码: <h:inputSecret value="#{user.password}"/><p>

            <h:commandButton value="送出"action="#{user.verify}"/>

        </h:form>

    </f:view>

 </body>

 </html>

当要根据verify运转结果来支配页面流程时,action属性中动用JSF Expression
Language”#{user.verify}”,如此JSF就理解必须依据verify传回的结果来导航页
面。<h:outputText>能够抽取内定的Bean之属性值,当使用者因验证错误而被送回原页面时,那些破绽百出音讯就能够来得在页面上。

2、JSF中的UI标签:

一.四导航规则设置

在JSF中是依据faces-config.xml中<navigation-rule>设定,以决定在适合的基准建霎时,该连结至哪一个页面,3个为主的设定如下:

<navigation-rule>

        <from-view-id>/pages/index.jsp</from-view-id>

        <navigation-case>

            <from-outcome>success</from-outcome>

            <to-view-id>/pages/welcome.jsp</to-view-id>

        </navigation-case>

        <navigation-case>

            <from-outcome>failure</from-outcome>

            <to-view-id>/pages/index.jsp</to-view-id>

        </navigation-case>

</navigation-rule>

对此JSF,每二个视图(View)都有二个离奇的辨识(identifier),称之为View
ID,在JSF中的View
ID是从Web应用程序的环境相对路线开端猜测,设定时都以以“/”作为初叶,即便您请求时的门路是/pages/index.faces,则JSF会将
扩张名改为/pages/index.jsp,以此作为view-id。在<navigation-rule>中的<from-
view-id>是个采用性的定义,它规定了来自页面包车型大巴原则,<navigation-case>中定义各类导览条
件,<from-outcome>定义当窗体结果符合的尺码时,各自改导向哪1个指标页面,指标页面是在<to-view-
id>中定义。您还足以在<navigation-case>中投入<from-action>,进一步规范窗体结果必须
依据哪七个动作方法(action method),个中是行使 JSF Expression Language
来设定,例如:

<navigation-rule>

        <from-view-id>/pages/index.jsp</from-view-id>

        <navigation-case>

            <from-action>#{user.verify}</from-action>

            <from-outcome>success</from-outcome>

            <to-view-id>/pages/welcome.jsp</to-view-id>

        </navigation-case>

</navigation-rule>

在导航时,预设都是选取forward的法门,您可以在<navigation-case>中进入一个<redirect/>,让JSF发出让浏览珍视新导向(redirect)的header,让浏览器主动须要新网页,例如:

<navigation-rule>

        <from-view-id>/pages/index.jsp</from-view-id>

        <navigation-case>

            <from-outcome>success</from-outcome>

            <to-view-id>/pages/welcome.jsp</to-view-id>

            <redirect/>

        </navigation-case>

</navigation-rule>

你的源于网页大概是有个别特定模块,例如在/admin/下的页面,您能够在<from-view-id>中动用wildcards(通配符),也正是利用“*”字符,例如:

<navigation-rule>

        <from-view-id>/admin/*</from-view-id>

        <navigation-case>

            <from-action>#{user.verify}</from-action>

            <from-outcome>success</from-outcome>

            <to-view-id>/pages/welcome.jsp</to-view-id>

       </navigation-case>

</navigation-rule>

在上头的设定中,只要来源网页是从/admin来的,都足以开始测试接下去的<navigation-case>。

  <from-view-id>假诺未有设定,表示来源网页不作限制,您也得以使用
* 显式的在概念档中注脚,例如:

<navigation-rule>

        <from-view-id>/*</from-view-id>

</navigation-rule>

可能是那样:

<navigation-rule>

        <from-view-id>*</from-view-id>

</navigation-rule>

JSF与JSP的竹签的界别在于,JSF的标签能够使用value,binding,action和actionListener等属性直接绑定到托管Bean上边去。

1.5 JSF Expression Language

JSF Expression
Language搭配JSF标签来利用,是用来存取数据对象的一个归纳语言。JSF
EL(ExpressionLanguage)是以“#”开端,将变量或表明式放置在Unknown
macro:“{”与“}”之间,例如:

 

#{someBeanName}

变量名称能够是faces-config.xml中定义的名号,要是是Bean的话,能够透过使用“.”
运算子来存取它的性质,例如:

<f:view>

    <h:outputText value="#{userBean.name}"/>

</f:view>

在JSF卷标的品质上,“””与“””(或“’”与“’”)之间一旦含有EL,则会加以运算,您也能够这么使用它:

<f:view>

    名称,年龄:<h:outputTextvalue="#{userBean.name}, #{userBean.age}"/>

</f:view>

叁个举办的结果或许是这么展现的:名称,年龄:Justin, 2九

EL的变量名也足以程序实行进度中所发表的称谓,或是JSF
EL预设的包罗对象,例如上边包车型地铁次序选取param隐含对象来获得使用者输入的参数:

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

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

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

 <html>

   <head>

     <title></title>

   </head>

   <body>

     <f:view>

        <b> 您好, <h:outputText value="#{param.name}"/> </b>

     </f:view>

   </body>

 </html>

param是JSF
EL预设的涵盖对象变量,它表示request全体参数的集聚,实际是三个java.util.Map型态对象,JSF所提供的带有对象,大概上相应于
JSP隐含物件,不过JSF隐含对象移除了pageScope与pageContext,而扩张了facesContext与view,它们分别对应于
javax.faces.context.FacesContext与javax.faces.component.UIViewRoot。

对于Map型态对象,我们得以行使“.”运算子钦命key值来抽出对应的value,也得以动用“[”与“]”来指定,例如:

<f:view>

    <b> 您好, <h:outputText value="#{param[‘name’]}"/> </b>

</f:view>

在“[”与“]”之间,也得以放置任何的变量值,例如:

<f:view>

    <h:outputText value="#{someBean.someMap[user.name]}"/>

 </f:view>

若果变量是List型态或数组的话,则能够在“[]”中钦命索引,例如:

<f:view>

     <h:outputText value="#{someBean.someList[0]}"/>

     <h:outputText value="#{someBean.someArray[1]}"/>

     <h:outputTextvalue="#{someBean.someListOrArray[user.age]}"/>

</f:view>

你也能够钦赐字面常数,对于true、false、字符串、数字,JSF
EL会尝试举行调换,例如:

<h:outputText value="#{true}"/>

<h:outputText value="#{‘This is a test’}"/>

假如要出口字符串,必须以单引号 ‘
或双自变量”括住,如此才不会被感觉是变量名称。在发表变量名称时,要注意不可与JSF的保留字或根本词同名,例如不可取以下那些名称:

true false null div mod and or not eq ne
lt gtle ge instanceof empty

动用EL,您可以直接推行局部算术运算、逻辑运算与关系运算,其使用如同同在相似常见的程序语言中之运算。算术运算子有:加法
(+), 减法 (-), 乘法 (*), 除法 (/ or div) 与余除 (% or mod)
。上边是算术运算的一对事例:

表达式

结果

#{1}

1

#{1 + 2}

3

#{1.2 + 2.3}

3.5

#{1.2E4 + 1.4}

12001.4

#{-4 – 2}

-6

#{21 * 2}

42

#{3/4}

0.75

#{3 div 4}

0.75,除法

#{3/0}

Infinity

#{10%4}

2

#{10 mod 4}

2,也是余除

#{(1==2) ? 3 : 4}

4

就好像在Java语法同样 (expression ? result壹 :
result二)是个安慕希运算,expression为true展现result一,false突显result2。逻辑运算
有:and(或&&)、or(或!!)、not(或!)。1些例证为:

表达式

结果

#{true and false}

false

#{true or false}

true

#{not true}

false

关系运算有:小于Less-than (< or lt)、大于Greater-than (> or
gt)、小于或等于Less-than-or-equal (<= or
le)、大于或等于Greater-than-or-equal (>= or ge)、等于Equal (== or
eq)、不等于Not Equal (!= or
ne),由英文名称能够取得lt、gt等运算子之缩写词,以下是汤姆cat的有的例证:

表达式

结果

#{1 < 2}

true

#{1 lt 2}

true

#{1 > (4/2)}

false

#{1 > (4/2)}

false

#{4.0 >= 3}

true

#{4.0 ge 3}

true

#{4 <= 3}

false

#{4 le 3}

false

#{100.0 == 100}

true

#{100.0 eq 100}

true

#{(10*10) != 100}

false

#{(10*10) ne 100}

false

右侧是运算子的运用格局,左侧的是运算结果,关系运算也能够用来相比较字符或字符串,按字典顺序来调整相比结实,例如:

表达式

结果

#{‘a’ < ‘b’}

true

#{‘hip’ > ‘hit’}

false

#{‘4’ > 3}

true

EL运算子的举行优先级与Java运算子对应,假如有困惑的话,也能够运用括号()来自行决定先后顺序。

JSF包蕴两组标签库:jsf_core.tld宗旨标签库和html_basic。tld
HTML标签库。

1.六国际化音讯

JSF的国际化(Internnationalization)消息处理是基于Java对国际化的支撑,您能够在三个资源消息财富文件中集合保管音信财富,资源文件的名目是.properties,而内容是称呼与值的配对,例如:

messages.properties

titleText=JSF Demo

 hintText=Please input your name and password

 nameText=name

 passText=password

 commandText=Submit

财富文件名称由basename加上语言与位置来构成,例如:

* basename.properties

    *basename_en.properties

    *basename_zh_cn.properties

尚未点名语言与所在的basename是预设的财富档名称,JSF会依照浏览器送来的Accept-Languageheader中的内容来决定该应用哪三个能源档名称,例如:

Accept-Language: zh_cn, en-US,
en

一经浏览器送来这几个header,则预设会利用繁体普通话,接着是美式英文,再来是英文语系,假诺找不到对应的情报财富文件,则会动用预设的信息能源文件。

出于情报能源文件必须是ISO-885玖-壹编码,所以对于非西方语系的处理,必须先将之转变为Java
UnicodeEscape格式,例如您能够先在消息能源文件中写下以下的剧情:

messages_zh_cn.txt

titleText=JSF示范

 hintText=请输入名称与密码

 nameText=名称

 passText=密码

 commandText=送出

接下来利用JDK的工具程序native2ascii来调换,例如:
native2ascii -encoding
Big5messages_zh_cn.txt messages_zh_cn.properties

转移后的剧情会如下:

messages_zh_cn.properties

titleText=JSF\u793a\u7bc4

hintText=\u8acb\u8f38\u5165\u540d\u7a31\u8207\u5bc6\u78bc

nameText=\u540d\u7a31

passText=\u5bc6\u78bc

commandText=\u9001\u51fa

接下去你能够利用<f:loadBundle>卷标来钦点加载音信能源,四个例证如下:

index.jsp

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

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

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

 

 <f:view>

 <f:loadBundle basename="messages" var="msgs"/>

 <html>

 <head>

 <title><h:outputText value="#{msgs.titleText}"/></title>

 </head>

 <body>

    <h:form>

        <h3><h:outputText value="#{msgs.hintText}"/></h3>

        <h:outputText value="#{msgs.nameText}"/>:

                <h:inputText value="#{user.name}"/><p>

        <h:outputText value="#{msgs.passText}"/>:

                <h:inputSecret value="#{user.password}"/><p>

        <h:commandButton value="#{msgs.commandText}"actionListener="#{user.verify}"

                        action="#{user.outcome}"/>

   </h:form>

 </body>

 </html>

 </f:view>

如此1来,如若你的浏览器预设接受zh_cn语系的话,则页面上就足以浮现中文,不然预设将以英文显示,也正是messages.properties的始末,为了能显得多国语系,我们设定网页编码为UTF-8。<f:view>能够设定locale
属性,直接钦命所要使用的语系,例如:

<f:view locale="zh_cn">

<f:loadBundle basename="messages" var="msgs"/>

直接钦赐以上的话,则会选用繁体中文来展现,JSF会遵照<f:loadBundle>的basename
属性加上<f:view>的locale属性来支配要使用哪四个新闻能源文件,就上例来讲,正是行使
messages_zh_cn.properties,假使设定为以下的话,就会选择messages_en.properties:

<f:view locale="en">

<f:loadBundle basename="messages" var="msgs"/>

您也得以在faces-config.xml中设定语系,例如:

<faces-config>

    <application>

        <local-config>

            <default-locale>en</default-locale>

            <supported-locale>zh_cn</supported-locale>

        </local-config>

    </application>

</faces-config>

在<local-config>一定有一个<default-locale>,
而<supported-locale>能够有大多少个,那告诉JSF您的应用程序帮助什么语系。当然,如若您能够提供二个取舍让使用者选拔本身的语系会是更加好的办法,例如依照user那一个Bean的locale属性来调控页面语系:

<f:view locale="#{user.locale}">

<f:loadBundle basename="messages" var="msgs"/>

在页面中设定三个窗体,能够让使用者选用语系,例如设定单选按键:

<h:selectOneRadio value="#{user.locale}">

     <f:selectItem itemValue="zh_cn"itemLabel="#{msgs.zh_cnText}"/>

     <f:selectItem itemValue="en"itemLabel="#{msgs.enText}"/>

</h:selectOneRadio>

贰.一、JSF主题标签库:

2.  Managed Beans

JSF使用Bean来完结逻辑层与表现层分离的目标,Bean的田管集中在组态档案中,您假诺修改组态档案,就足以修改Bean之间的相依关系。

f:actionListener
f:attribute
f:convertDateTime
f:convertNumber
f:converter
f:facet
f:loadBundle
f:param
f:phaseListener
f:selectItem
f:selectItems
f:setPropertyActionListener
f:subview
f:validateDoubleRange
f:validateLength
f:validateLongRange
f:validator
f:valueChangeListener
f:verbatim
f:view

2.1 Backing Beans

JSF使用JavaBean来实现程序逻辑与视图分离的指标,在JSF中的Bean其角色是属于Backing
Bean,又称之为Glue
Bean,其职能是在真的的工作逻辑Bean及UI组件之间搭起桥梁,在Backing
Bean中会呼叫业务逻辑Bean处理使用者的呼吁,大概是将业务处理结果放置个中,等待UI组件收取个中的值并出示结果给使用者。JSF将Bean的管
理集中在faces-config.xml中,二个事例如下:

 <managed-bean>
    <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.UserBean
        </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>

 

其一例子大家在第三个JSF程序看过,<managed-bean-class>设定所要使用的Bean序列,<managed-bean-name>设定之称号,可供大家在JSF页面上使用Expression
Language来获得或设定Bean的品质,例如:

<h:inputText value="#{user.name}"/>

  

<managed-bean-scope>设定Bean的水保范围,您能够设定为request、session与
application,设定为request时,Bean的幸存时间为呼吁阶最,设定为session则在使用者应用程序交互初阶,直到关闭浏览器或显
式的收尾会话停止(例如注销程序),设定为application的话,则Bean会一向并存,直到应用程序关闭截至。

  您仍是能够将现成范围设定为none,当设定为none时会在必要的时候生成3个新的Bean,例如您在一个method中想要生成1个暂且的Bean,就足以将之设定为none。

  在JSF页面上要收获Bean的属性,是应用JSF表示语言 (Expression
Language),要专注到的是,JSF代表语言是写成 #{expression},而
JSP表示语言是写成
${expression},因为表示层大概是应用JSP,所以必须尤其区分,其余要留意的是,JSF的卷标上之性质设定时,只接受JSF表示语言。

至于个标签的详细介绍,能够参见JSF自带的辅助文书档案:

二.二Beans 的组态与设定

JSF预设会读取faces-config.xml中关于Bean的定义,假诺想要自行设置定义档的称号,我们是在web.xml中提供javax.faces.CONFIG_FILES参数,例如:

<web-app>
   <context-param>
      <param-name>javax.faces.CONFIG_FILES</param-name>
      <param-value>/WEB-INF/beans.xml</param-value>
   </context-param>   
</web-app>

 

定义档能够有多少个,中间以“,”区隔,例如:

/WEB-INF/navigation.xml,/WEB-INF/beans.xml

 

三个Bean最主旨要定义Bean的称号、连串与存活范围,例如:

<managed-bean>
    <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.UserBean
        </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

 

 如若要在其余门类中赢得Bean对象,则足以先拿走javax.faces.context.FacesContext,它意味着了JSF近年来的实行环境目的,接着尝试获得javax.faces.el.ValueBinding对象,从中获得钦定的Bean对象,例如:

FacesContext context = FacesContext.getCurrentInstance();
ValueBinding binding = context.getApplication().createValueBinding("#{user}");
UserBean user = (UserBean) binding.getValue(context);

 

澳门永利备用网址,比方只是要品尝获得Bean的某部属性,则能够如下:

FacesContext context = FacesContext.getCurrentInstance();
ValueBinding binding = context.getApplication().createValueBinding("#{user.name}");
String name = (String) binding.getValue(context);

 

1经有须要在启始Bean时,自动安装属性的始发值,则能够如下设定:

<managed-bean>
    <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.UserBean
        </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
        <property-name>name</property-name>
        <value>caterpillar</value>
    </managed-property>
    <managed-property>
        <property-name>password</property-name>
        <value>123456</value>
    </managed-property>
</managed-bean>

  

假若要设定属性为null值,则足以行使<null-value/>标签,例如:

    <managed-property>
        <property-name>name</property-name>
        <null-value/>
    </managed-property>
    <managed-property>
        <property-name>password</property-name>
        <null-value/>
    </managed-property>

  

本来,您的属性不肯定是字符串值,大概会是int、float、boolean等等型态,您能够设定<value>
值时钦赐那个值的字符串名称,JSF会尝试进行调换,例如设定为true时,会尝试采纳Boolean.valueOf()方法调换为boolean的
true,以下是局地也许开展的更动:

型态

转换

short、int、long、float、double、byte,或相应的Wrapper类别

尝试使用Wrapper的valueOf()进行转换,如果没有设置,则设为0

boolean 或 Boolean

尝试使用Boolean.valueOf()进行转换,如果没有设置,则设为false

char 或 Character

取设置的第一个字符,如果没有设置,则设为0

String 或 Object

即设定的字符串值,如果没有设定,则为空字符串new String("")

  

您也得以将另外发生的Bean设定给另3个Bean的属性,例如:

 <managed-bean>
    <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.UserBean
        </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>

 

 <managed-bean>
    <managed-bean-name>other</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.OtherBean
        </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    <managed-property>
      <property-name>user</property-name>
      <value>#{user}</value>
    </managed-property>
 </managed-bean>

  

在地点的设定中,在OtherBean中的user属性,接受三个UserBean型态的对象,我们设定为前多少个称呼为user的UserBean对象。

JSF解压目录\tlddocs\index.html

2.3 Beans上的 List和Map

要是你的Bean上有接受List或Map型态的性格,则您也足以在组态档案中央直属机关接设定那几个属性的值,1个例子如下:

<managed-bean>
    <managed-bean-name>someBean</managed-bean-name>
      <managed-bean-class>
          onlyfun.caterpillar.SomeBean
      </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>

 

    <managed-property>
        <property-name>someProperty</property-name>
        <list-entries>
            <value-class>java.lang.Integer</value-class>
            <value>1</value>
            <value>2</value>
            <value>3</value>
        </list-entries>
    </managed-property>
</managed-bean>

 

 那是三个设定接受List型态的品质,大家应用<list-entries>卷标钦定将设定贰个List对象,当中<value-class>钦命将存入List的型态,而<value>钦点其值,假使是骨干型态,则会尝试运用钦点的<value-class>来作Wrapper连串。

 

设定Map的话,则是应用<map-entries>标签,例如:

 <managed-bean>
    <managed-bean-name>someBean</managed-bean-name>
    <managed-bean-class>
       onlyfun.caterpillar.SomeBean
    </managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>

 

    <managed-property>
        <property-name>someProperty</property-name>
        <map-entries>
            <value-class>java.lang.Integer</value-class>
            <map-entry>
                <key>someKey1</key>
                <value>100</value>
            </map-entry>
            <map-entry>
                <key>someKey2</key>
                <value>200</value>
            </map-entry>
        </map-entries>
    </managed-property>
 </managed-bean>

  

由于Map对象是以key-value对的章程来存入,所以大家在每三个<map-entry>中利用<key>
与<value>标签来分别钦命。您也得以间接像设定Bean一样,设定一个List或Map对象,例如在JSF附的范例中,有这么的设定:

   <managed-bean>
        <description>
            Special expense item types
        </description>
      <managed-bean-name>specialTypes</managed-bean-name>
      <managed-bean-class>
          java.util.TreeMap
      </managed-bean-class>
      <managed-bean-scope>application</managed-bean-scope>
      <map-entries>
         <value-class>java.lang.Integer</value-class>
         <map-entry>
            <key>Presentation Material</key>
            <value>100</value>
         </map-entry>
         <map-entry>
            <key>Software</key>
            <value>101</value>
         </map-entry>
         <map-entry>
            <key>Balloons</key>
            <value>102</value>
         </map-entry>
        </map-entries>
  </managed-bean>

  

而范例中另两个设定List的事例如下:

  <managed-bean>
    <managed-bean-name>statusStrings</managed-bean-name>
    <managed-bean-class>
        java.util.ArrayList
    </managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <list-entries>
      <null-value/>
      <value>Open</value>
      <value>Submitted</value>
      <value>Accepted</value>
      <value>Rejected</value>
    </list-entries>
  </managed-bean>

2.2、JSF的HTML标签:

三. 数据调换与认证

转变器(Converter)援助模型与视图之间的多寡转变,验证器(Validator)扶助开展语意核准(Semantic
Validation)。

h:commandButton
h:commandLink
h:dataTable
h:form
h:graphicImage
h:inputHidden
h:inputSecret
h:inputText
h:inputTextarea
h:message
h:messages
h:outputFormat
h:outputLabel
h:outputLink
h:outputText
h:panelGrid
h:panelGroup
h:selectBooleanCheckbox
h:selectManyCheckbox
h:selectManyListbox
h:selectManyMenu
h:selectOneListbox
h:selectOneMenu
h:selectOneRadio
h:column

叁.壹正式转变器

Web应用程序与浏览器之间是选拔HTTP举行调换,全数传送的数量大致都以字符串文字,而Java应用程序本人基本上则是指标,所以指标数据必须经过转变传送给浏览器,而浏览器送来的数码也非得转变为对象才干接纳。

  JSF定义了1层层专业的调换器(Converter),对于着力数据型态(primitive
type)或是其Wrapper种类,JSF会使用javax.faces.Boolean、javax.faces.Byte、
javax.faces.Character、javax.faces.Double、javax.faces.Float、
javax.faces.Integer、javax.faces.Long、javax.faces.Short等机关进行转变,对于
BigDecimal、BigInteger,则会利用javax.faces.BigDecimal、javax.faces.BigInteger自
动实行改变。

  至于DateTime、Number,大家能够使
用<f:convertDateTime>、<f:convertNumber>标签实行调换,它们各自提供有部分轻巧的性质,
能够让大家在改变时钦定1些转变的格式细节。来看个简易的例子,首先大家定义二个简易的Bean:

UserBean.java

package onlyfun.caterpillar;

 

 import java.util.Date;

 public class UserBean

{
    private Date date = new Date();
   
    public Date getDate()

{
        return date;
    }

 

public void setDate(Date date)

{
        this.date = date;
    }
 }

  

本条Bean的属性接受Date型态的参数,按理来讲,接收到HTTP传来的数码中若有有关的日期音讯,我们无法不剖析那几个信息,再调换为Date对象,但是我们得以使用JSF的专业转变器来支援这项工作,例如:

index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
 <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
 <%@page contentType="text/html;charset=Big5"%>

 <f:view>

 <html>
 <head>
 <title>转换器示范</title>
 </head>
 <body>

 设定的日期是:
           <b>
             <h:outputText value="#{user.date}">
                 <f:convertDateTime pattern="dd/MM/yyyy"/>
             </h:outputText>
           </b>

    <h:form>
        <h:inputText id="dateField" value="#{user.date}">
            <f:convertDateTime pattern = "dd/MM/yyyy"/>
        </h:inputText>
        <h:message for="dateField" style="color:red"/>
        <br>
        <h:commandButton value="送出" action="show"/>
    </h:form>
 </body>
 </html>
</f:view>

  

在<f:convertDate提姆e>中,大家利用pattern钦定日期的体裁为dd/MM/yyyy,即「日/月/公元」格
式,假如转变错误,则<h:message>能够显得错误音讯,for属性参考至<h:inputText>
的id属性,表示将关于date菲尔德的不当信息显示出来。借使faces-config.xml是那样定义的:

faces-config.xml

<?xml version="1.0"?>
 <!DOCTYPE faces-config PUBLIC
 "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
 "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

 

 <faces-config>
    <navigation-rule>
        <from-view-id>/*</from-view-id>
        <navigation-case>
            <from-outcome>show</from-outcome>
            <to-view-id>/pages/index.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>
      
    <managed-bean>
        <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.UserBean
        </managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
 </faces-config>

  

第3回连上页面时显示的画面如下:

 

  

如您所见到的,转变器自动依pattern设定的样式将Date对象格式化了,当您依格式输入数据并送出后,调换器也会自动将你输入的数据转换为Date对象,假若转变时发生错误,则会现出以下的新闻:

 

   <f:convertDateTime>卷标还有多少个可用的习性,您可以参考Tag
LibraryDocumentation
的求证,而依照类似的点子,您也足以采用<f:convertNumber>来调换数值。

关于个标签的详实介绍,能够参照JSF自带的相助文书档案:

三.贰自订调换器

除开辟取规范的转变器之外,您还是可以够自动定制您的调换器,您能够实作javax.faces.convert.Converter接口,那么些接口有三个要实作的主意:

public Object getAsObject(FacesContext context, UIComponent component, String str);
public String getAsString(FacesContext context, UIComponent component, Object obj);

  

简言之的说,第3个方法会接收从客户端经由HTTP传来的字符串数据,您在首先个点子少将之转变为你的自订对象,那个自订对象将会自行设定给您钦点的
Bean对象;第2个措施正是将从你的Bean对象得到的目标转变为字符串,如此才能藉由HTTP传回给客户端。间接以1个归纳的例证来作表达,假使您有
一个User种类:

User.java

package onlyfun.caterpillar;

 

 public class User {
    private String firstName;
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
 }

  

以此User体系是我们调换器的目的对象,而你有一个GuestBean连串:

GuestBean.java

package onlyfun.caterpillar;

 

 public class GuestBean {
    private User user;
   
    public void setUser(User user) {
        this.user = user;
    }
   
    public User getUser() {
        return user;
    }
 }

  

以此Bean上的性质直接传回或收受User型态的参数,大家来实作八个归纳的转换器,为HTTP字符串与User对象开展转变:

UserConverter.java

package onlyfun.caterpillar;

 

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

public class UserConverter implements Converter {

public Object getAsObject(FacesContext context, UIComponent component, String str) throws ConverterException {

            String[] strs = str.split(",");
            User user = new User();
       
            try {
                user.setFirstName(strs[0]);
                user.setLastName(strs[1]);
            }
            catch(Exception e) {
                // 转换错误,简单的丢出例外
                throw new ConverterException();
            }
       
            return user;
    }

 

    public String getAsString(FacesContext context, UIComponent component,Object obj)
                                 throws ConverterException {
            String firstName = ((User) obj).getFirstName();
            String lastName = ((User) obj).getLastName();
       
            return firstName + "," + lastName;
    }
 }

  

实作完毕那几个调换器,大家要告知JSF那件事,那是在faces-config.xml中做到注册:

faces-config.xml

<?xml version="1.0"?>
 <!DOCTYPE faces-config PUBLIC
 "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
 "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

 

 <faces-config>
    <navigation-rule>
        <from-view-id>/*</from-view-id>
        <navigation-case>
            <from-outcome>show</from-outcome>
            <to-view-id>/pages/index.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>
      
    <converter>
        <converter-id>onlyfun.caterpillar.User</converter-id>
        <converter-class>
            onlyfun.caterpillar.UserConverter
        </converter-class>
    </converter>

    <managed-bean>
        <managed-bean-name>guest</managed-bean-name>
        <managed-bean-class>
            onlyfun.caterpillar.GuestBean
        </managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
 </faces-config>

  

挂号转变器时,需提供转变器度和胆识别(Converter
ID)与转变器体系,接下去要在JSF页面中利用调换器的话,正是点名所要使用的转变器度和胆识别,例如:

index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>

 

 <f:view>

 <html>
 <head>
 <title>自订转换器</title>
 </head>
 <body>

 Guest名称是:<b>
           <h:outputText value="#{guest.user}" converter="onlyfun.caterpillar.User"/>
           </b>

    <h:form>
        <h:inputText id="userField" value="#{guest.user}" converter="onlyfun.caterpillar.User"/>
        <h:message for="userField" style="color:red"/>
        <br>
        <h:commandButton value="送出" action="show"/>
    </h:form>
 </body>
 </html>
 </f:view>

 

您也足以<f:converter>卷标并动用converterId属性来钦命调换器,例如:

<h:inputText id="userField" value="#{guest.user}">
     <f:converter converterId="onlyfun.caterpillar.User"/>
</h:inputText>

  

除开向JSF注册转变器之外,还有二个方法能够不用登记,就是平昔在Bean上提供3个获取转变器的办法,例如:

GuestBean.java

package onlyfun.caterpillar;

import javax.faces.convert.Converter;

 public class GuestBean {

    private User user;
    private Converter converter = new UserConverter();
   
    public void setUser(User user) {
        this.user = user;
    }
   
    public User getUser() {
        return user;
    }
   
    public Converter getConverter() {
        return converter;
    }
 }

  

从此方可一贯结合JSFExpression Language 来内定转变器:

<h:inputText id="userField" value="#{guest.user}" converter="#{guest.converter}"/>

JSF解压目录\tlddocs\index.html

三.3规范验证器

当应用程序供给使用者输入数据时,必然思索到使用者输入数据之不易,对于使用者的输入必须进行查证,核实要求的二种评释是语法核实(Synatic
Validation)与语意核算(Semantic Validation)。

  语法核实是要检查使用者输入的数码是还是不是适合大家所须要的格式,最大旨的正是反省使用者是还是不是填入了字段值,或是字段值的长短、大小值等等是或不是相符
须求。语意核准是在语法核准之后,在格式符合要求之后,我们尤其证实使用者输入的数量语意上是还是不是正确,例如检查使用者的名号与密码是不是合营。

在简练的导航 (Navigation)
中,我们对使用者名称与密码检查是或不是合营,那是语意核实,大家得以选择JSF所提供的正式验证器,为其投入语法查证,例如:

index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>
 <html>
 <head>
 <title>验证器示范</title>
 </head>
 <body>
    <f:view>
        <h:messages layout="table" style="color:red"/>
        <h:form>
            <h3>请输入您的名称</h3>
            <h:outputText value="#{user.errMessage}"/><p>
           名称: <h:inputText value="#{user.name}" required="true"/><p>
           密码: <h:inputSecret value="#{user.password}" required="true">
             <f:validateLength minimum="6"/>
         </h:inputSecret><p>
            <h:commandButton value="送出" action="#{user.verify}"/>
        </h:form>
    </f:view>
 </body>
 </html>

  

在<h:inputText>、</h:inputSecret>中,大家设定了required属性为true,那意味这么些字段一定要输入值,我们也在</h:inputSecret>设定了<f:
validateLength>,并设定其minimum属性为陆,那象征那么些字段最少必要四个字符。

  那1遍在错误音信的展现上,咱们利用<h:messages>标签,当有认证错误发生时,相关的荒谬信息会搜集起来,使用<h:messages>卷标能够贰次将有着的错误音讯展现出来。上边是一个表达错误的消息展现:

 

  

JSF提供了二种标准认证
器:<f:validateDoubleRange>、<f:validateLongRange>、<f:validateLength>,
您能够独家查询它们的 Tag
LibraryDocumentation,精晓他们有如何属性能够应用,或然是参考Using the
Standard Validators 那篇文章中有有关规范验证器的验证。

二.三、UI标签的通用属性:

三.四自订验证器

您能够自订自个儿的验证器,所供给的是实作javax.faces.validator.Validator接口,例如大家实作二个大致的密码验证器,检查字符长度,以及密码中是还是不是包蕴字符与数字:

PasswordValidator.java

package onlyfun.caterpillar;

 

 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.Validator;
 import javax.faces.validator.ValidatorException;

 

 public class PasswordValidator implements Validator {

    public void validate(FacesContext context,UIComponent component,Object obj)
            throws ValidatorException {

        String password = (String) obj;

       
        if(password.length() < 6) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                 "字符长度小于6", "字符长度不得小于6");
            throw new ValidatorException(message);
        }
       
        if(!password.matches(".+[0-9]+")) {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                   "密码必须包括字符与数字", "密码必须是字符加数字所组成");
            throw new ValidatorException(message);
        }
    }
 }

  

您要实作javax.faces.validator.Validator接口中的validate()方法,要是证实错误,则丢出二个ValidatorException,它接受二个FacesMessage对象,这些指标接受八个参数,分别代表信息的要紧程度(INFO、WARAV4N、
E奇骏ROHummerH二、FATAL)、音信概述与详细新闻内容,那几个情报将能够使用<h:messages>或<h:
message>卷标呈现在页面上。接下来要在faces-config.xml中登记验证器的辨别(Validater
ID),要进入以下的始末:

faces-config.xml

<?xml version="1.0"?>
 <!DOCTYPE faces-config PUBLIC
 "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
 "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

 

 <faces-config>
    <validator>
        <validator-id>
            onlyfun.caterpillar.Password
        </validator-id>
        <validator-class>
            onlyfun.caterpillar.PasswordValidator
        </validator-class>
    </validator>
 </faces-config>

  

要运用自订的验证器,我们得以采纳<f:validator>卷标并设定validatorId属性,例如:

 <h:inputSecret value="#{user.password}" required="true">
    <f:validator validatorId="onlyfun.caterpillar.Password"/>
 </h:inputSecret><p>

  

您也足以让Bean自行承担验证的行事,能够在Bean上提供一个表明办法,那些措施未有传到值,并可以接收FacesContext、UIComponent、Object七个参数,例如:

UserBean.java

package onlyfun.caterpillar;

 import javax.faces.application.FacesMessage;
 import javax.faces.component.UIComponent;
 import javax.faces.context.FacesContext;
 import javax.faces.validator.ValidatorException;

 public class UserBean {
     public void validate(FacesContext context,
                         UIComponent component,
                         Object obj)
            throws ValidatorException {
        String password = (String) obj;
       
        if(password.length() < 6) {
            FacesMessage message = new FacesMessage(
                 FacesMessage.SEVERITY_ERROR,
                 "字符长度小于6",
                 "字符长度不得小于6");
            throw new ValidatorException(message);
        }
        if(!password.matches(".+[0-9]+")) {
            FacesMessage message = new FacesMessage(
                   FacesMessage.SEVERITY_ERROR,
                   "密码必须包括字符与数字",
                   "密码必须是字符加数字所组成");
            throw new ValidatorException(message);
        }
    }
 }

  

进而可以在页面下如下使用验证器:

 <h:inputSecret value="#{user.password}"  required="true"  validator="#{user.validate}"/>

JSF的UI大都会生成一个或多少个HTML标签,所以利用那么些UI标签有时壹些属性是通用的:

3.5谬误消息处理

在行使专业调换器或验证器时,当爆发错误时,会有部分预设的错误音信显示,这么些音讯能够选用<h:messages>或<h:message>卷标来呈现出来,而那些预设的荒唐消息也是足以修改的,您所要作的是提供七个音信托投财富文件,例如:
messages.properties

javax.faces.component.UIInput.CONVERSION=Format Error.
javax.faces.component.UIInput.REQUIRED=Please input your data.

  

javax.faces.component.UIInput.CONVE奇骏SION是用来设定当调换器发现错误时显示的新闻,而
javax.faces.component.UIInput.REQUIRED是在标签设定了required为true,而使用者未有在字段输入时突显的荒谬信息。您要在faces-config.xml中告诉JSF您使用的新闻文件名称,例如:
faces-config.xml

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
  <application>
    <local-config>
      <default-locale>en</default-locale>
      <supported-locale>zh_TW</supported-locale>
    </local-config>
    <message-bundle>messages</message-bundle>
  </application>
</faces-config>

  

在那边大家设定了新闻档案的名目为messages_xx_YY.properties,其中xx_YY是遵照你的Locale来调整,调换器或验证器的错误信息如若有设定来讲,就使用设定值,要是未有设定以来,就应用暗中认可值。

验证器错误信息,除了上边的javax.faces.component.UIInput.REQUIRED之外,还有以下的多少个:

讯息识别

预设讯息

用于

javax.faces.validator.NOT_IN_RANGE

Validation Error: Specified attribute is not between the expected values of {0} and {1}.

DoubleRangeValidator LongRangeValidator,{0}与{1}分别代表minimum与maximum所设定的属性

javax.faces.validator.DoubleRangeValidator.MAXIMUM、javax.faces.validator.LongRangeValidator.MAXIMUM

Validation Error: Value is greater than allowable maximum of ‘{0}’.

DoubleRangeValidator或LongRangeValidator,{0}表示maximum属性

javax.faces.validator.DoubleRangeValidator.MINIMUM、javax.faces.validator.LongRangeValidator.MINIMUM

Validation Error: Value is less than allowable minimum of ‘{0}’.

DoubleRangeValidator或LongRangeValidator,{0}代表minimum属性

javax.faces.validator.DoubleRangeValidator.TYPE、javax.faces.validator.LongRangeValidator.TYPE

Validation Error: Value is not of the correct type.

DoubleRangeValidator或LongRangeValidator

javax.faces.validator.LengthValidator.MAXIMUM

Validation Error: Value is greater than allowable maximum of ”{0}”.

LengthValidator,{0}代表maximum

javax.faces.validator.LengthValidator.MINIMUM

Validation Error: Value is less than allowable minimum of ”{0}”.

LengthValidator,{0}代表minimum属性

  

在您提供自订消息的时候,也能够提供{0}或{1}来设定展现相对的属性值,以提供详实正确的荒谬提醒信息。音信的彰显有概述消息与前述音信,假如是详述音信,则在辨别上助长
“_detail”,例如:

javax.faces.component.UIInput.CONVERSION=Error.
javax.faces.component.UIInput.CONVERSION_detail= Detail Error.

  

除此之外在情报财富文件中提供情报,您也能够在程序中动用FacesMessage来提供音信,例如在
自订验证器 中大家就这么用过:

if(password.length() < 6)

{
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"字符长度小于6",
"字符长度不得小于6");
throw new ValidatorException(message);

}

  

最棒的艺术是在音信托投能源文件中提供情报,这么1来若是大家要修改音信,就若是修改音信能源文件的始末,而不用修改程序,来看2个轻易易行的事例,假使我们的音讯能源文件中有以下的始末:

onlyfun.caterpillar.message1=This is message1.
onlyfun.caterpillar.message2=This is message2 with \{0} and \{1}.

  

则我们能够在程序中收获信息能源文件的内容,例如:

package onlyfun.caterpillar;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
improt javax.faces.component.UIComponent;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
public void xxxMethod(FacesContext context,
UIComponent component,
Object obj) {
// 取得应用程序代表对象
Application application = context.getApplication();
// 取得讯息档案主名称
String messageFileName =
application.getMessageBundle();
// 取得当前 Locale对象
Locale locale = context.getViewRoot().getLocale();
// 取得讯息绑定 ResourceBundle对象
ResourceBundle rsBundle =
ResourceBundle.getBundle(messageFileName, locale);
String message = rsBundle.getString(
"onlyfun.caterpillar.message1");
FacesMessage facesMessage = new FacesMessage(
FacesMessage.SEVERITY_FATAL, message, message);
}

  

接下去你能够将FacesMessage对象填入ValidatorException或ConverterException后再丢
出,FacesMessage建构时所使用的多个参数是人命关天程度、概述音信与前述音讯,严重程度有SEVEEvoqueITY_FATAL、
SEVERITY_ERROR、SEVERITY_WARN与SEVERITY_INFO两种。
即使急需在情报财富文件中设定{0}、{1}等参数,则足以如下:

String message = rsBundle.getString( "onlyfun.caterpillar.message2");
Object[] params = {"param1", "param2"};
message = java.text.MessageFormat.format(message, params);
FacesMessage facesMessage = new FacesMessage(
FacesMessage.SEVERITY_FATAL, message, message);

  

如此壹来,在展现音讯时,onlyfun.caterpillar.message贰的{0}与{壹}的地方就会被”param1″与”param2″所代替。

id
immediate:是否立即处理UIInput组件和实现了ActionSource接口的UI组件上事件
rendered:指定条件表达式,当条件表达式为true时才会绘制组件
required:指定用户是否必须为组件输入值
requeredMessage:与requered一起使用,如果没有输入时提示信息
value:该组件的值绑定到托管对象上
onblur
onchange
onclick
ondblclick
onfocus
onkeydown
onkeypress
onkeyup
onmousedown
onmousemove
onmouseout
onmouseover
onmouseup
style
styleClass
binding:将组件本身绑定到托管Bean

三.6自订转变和注明标签

在自订验证器中,大家的验证器只好证实一种pattern(+[0-9]+),大家意在得以在JSF页面上自订相配的pattern,但是由于大家使用<f:
validator>那几个通用的验证器标签,为了要能提供pattern属性,我们能够利用<f:attribute>标签来设置,例
如:

<h:inputSecret value="#{user.password}" required="true">
<f:validator validatorId="onlyfun.caterpillar.Password"/>
<f:attribute name="pattern" value=".+[0-9]+"/>
</h:inputSecret><p>

  

动用<f:attribute>卷标来设定属性,接着大家得以如下获得所设定的性质:

public void validate(FacesContext context,
UIComponent component,
Object obj)
throws ValidatorException {  
String pattern = (String)
component.getAttributes().get("pattern");
}

  

您也足以付出本人的1组求证卷标,并提供相关属性设定,那亟需领会JSPTag
Library的行文,所以请您先参考JSP/Servlet 中有至于JSP TagLibrary的介绍。

要付出验证器转用标签,您能够1直接轨javax.faces.webapp.ValidatorTag,这些项目可以帮您处理大部份的底细,您所急需的,就是重复定义它的createValidator()方法,大家以改写
自订验证器 中的PasswordValidator为例:

PasswordValidator.java
PasswordValidator.java
package onlyfun.caterpillar;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class PasswordValidator implements Validator {
private String pattern;

    public void setPattern(String pattern)

 {
        this.pattern = pattern;
    }

    public void validate(FacesContext context, UIComponent component, Object obj)

throws ValidatorException

{
String password = (String) obj;

if(password.length() < 6)

 {
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"字符长度小于6", "字符长度不得小于6");
throw new ValidatorException(message);

}

if(pattern != null && !password.matches(pattern))

{
FacesMessage message = new FacesMessage(
FacesMessage.SEVERITY_ERROR,
"密码必须包括字符与数字",
"密码必须是字符加数字所组成");
throw new ValidatorException(message);

}

}

}

注重的差距是我们提供了pattern属性,在validate()方法中开始展览验证时,是遵照大家所设定的pattern属性,接着大家一而再javax.faces.webapp.ValidatorTag来写作本身的求证标签:

PasswordValidatorTag.java

package onlyfun.caterpillar;

import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.webapp.ValidatorTag;

public class PasswordValidatorTag extends ValidatorTag

{
    private String pattern;

    public void setPattern(String pattern)

{
this.pattern = pattern;

}

 

protected Validator createValidator()

 {
Application application =
FacesContext.getCurrentInstance().
getApplication();
PasswordValidator validator =
(PasswordValidator) application.createValidator(
"onlyfun.caterpillar.Password");
validator.setPattern(pattern);
return validator;

}

}

  

application.createValidator()方法创制验证器对象时,是依照在faces-config.xml中登记验证器的鉴定分别(Validater
ID):
faces-config.xml

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
    <validator>
        <validator-id>
            onlyfun.caterpillar.Password
        </validator-id>
        <validator-class>
            onlyfun.caterpillar.PasswordValidator
        </validator-class>
    </validator>
</faces-config>

 

剩下来的做事,正是安顿tld描述档了,大家简要的定义一下:
taglib.tld

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

<taglib 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
web-jsptaglibrary_2_0.xsd"
version="2.0">

<description>PasswordValidator Tag</description>
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>co</short-name>
<uri>http://caterpillar.onlyfun.net</uri>

<tag>
<description>PasswordValidator</description>
<name>passwordValidator</name>
<tag-class>
onlyfun.caterpillar.PasswordValidatorTag
</tag-class>
<body-content>empty</body-content>
<attribute>
<name>pattern</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>

</taglib>

 

而作者辈的index.jsp改写如下:
index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="/WEB-INF/taglib.tld" prefix="co" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>验证器示范</title>
</head>
<body>
<f:view>
<h:messages layout="table" style="color:red"/>
<h:form>
<h3>请输入您的名称</h3>
<h:outputText value="#{user.errMessage}"/><p>
名称: <h:inputText value="#{user.name}"
required="true"/><p>
密码: <h:inputSecret value="#{user.password}"
required="true">
<co:passwordValidator pattern=".+[0-9]+"/>
</h:inputSecret> <p>
<h:commandButton value="送出"
action="#{user.verify}"/>
</h:form>
</f:view>
</body>
</html>

  

重中之重的距离是,我们应用了本身的验证器标签:

<co:passwordValidator pattern=".+[0-9]+"/>

  

假设要自订调换器标签,方法也是接近,您要作的是承接javax.faces.webapp.ConverterTag,并再次定义其createConverter()方法。

二.肆、<f:view>标签的常用属性:

4. 事件处理

JSF的风浪模型提供1个看似的桌面GUI事件情势,让熟稔GUI设计的人手也能高效上手Web程序设计。

locale:点名国家语言
renderKitId:JSF依照该属性值选用相应的绘制器工具箱来绘制该页面
beforePhase:绑定生命周期监听器(必须有public void
beforePhase(Java.faces.event.PhaseEvent)方式的签订契约),JSF会在各样生命周期阶段(除了回复视图)以前调用该办法。
afterPhase:绑定生命周期监听器(必须有public void
afterPhase(java.faces.event.Phase伊芙nt)情势的具名),JSF会在种种生命周期阶段(除了回复视图)之后调用该措施。

四.一动作事件

JSF帮助事件处理模型,尽管由于HTTP自个儿无状态(stateless)的天性,使得那些模型多少有个别地点仍不太一致,但JSF所提供的事件处理模型已足以让部分理念GUI程序的宏图职员,能够用接近的模子来开辟顺序。

在 轻便的导航 中,我们依照动作方法(action
method)的结果来支配要导向的网页,三个按键系结至八个艺术,那样的作法实际上尽管JSF所提供的简化的事件处理程序,在按键上利用action系
结至二个动作方法(action
method),实际上JSF会为其机动发出3个「预设的ActionListener」来处总管件,并依据其传回值来调整导向的页面。

假定你必要利用同1个办法来应付各类事件起点,并想要获得事件起点的相干新闻,您能够让处监护人件的章程接收3个javax.faces.event.Action伊芙nt事件参数,例如:

UserBean.java

package onlyfun.caterpillar;

import javax.faces.event.ActionEvent;

public class UserBean {
private String name;
private String password;
private String errMessage;
private String outcome;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setPassword(String password) {
this.password = password;
}

public String getPassword() {
return password;
}

public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}

public String getErrMessage() {
return errMessage;
}

public void verify(ActionEvent e) {
if(!name.equals("justin") ||
!password.equals("123456")) {
errMessage = "名称或密码错误" + e.getSource();
outcome = "failure";
}
else {
outcome = "success";
}
}

public String outcome() {
return outcome;
}
}

  

在上例中,大家让verify方法接收一个Action伊夫nt对象,当使用者按下按键,会自行发出Action伊芙nt对象表示事件源于,我们故意在错误音信之后如上事件源点的字符串描述,那样就足以在显示错误音信时一并出示事件起点描述。为了提供Action伊芙nt的存取技术,您的
index.jsp能够改写如下:
index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=Big5"%>
<html>
<head>
<title>第一个JSF程序</title>
</head>
<body>
<f:view>
<h:form>
<h3>请输入您的名称</h3>
<h:outputText value="#{user.errMessage}"/><p>
名称: <h:inputText value="#{user.name}"/><p>
密码: <h:inputSecret value="#{user.password}"/><p>
<h:commandButton value="送出" actionListener="#{user.verify}" action="#{user.outcome}"/>
</h:form>
</f:view>
</body>
</html>

  

关键改造的是开关上利用了actionListener属性,这种方法能够选拔二个ActionListener,JSF会先检查是或不是有钦点的
actionListener,然后再自小编批评是不是钦点了动作方法并发出预设的ActionListener,并依照其传回值导航页面。

假设你要登记多个ActionListener,例如当使用者按下开关时,顺便在记录文件中增添部分记录音信,您可以实作javax.faces.event.ActionListener,例如:

LogHandler.java

package onlyfun.caterpillar;

import javax.faces.event.ActionListener;
public class LogHandler implements ActionListener {
public void processAction(ActionEvent e) {
// 处理Log
}
}
VerifyHandler.java
package onlyfun.caterpillar;

import javax.faces.event.ActionListener;
….

public class VerifyHandler implements ActionListener {
public void processAction(ActionEvent e) {
// 处理验证
}
}

  

这么壹来,您就能够使用<f:actionListener>卷标向组件注册事件,例如:

<h:commandButton value="送出" action="#{user.outcome}">
<f:actionListener type="onlyfun.caterpillar.LogHandler"/>
<f:actionListener type="onlyfun.caterpillar.VerifyHandler"/>
</h:commandButton>

  <f:actionListener>会自行发出type所钦赐的对象,并呼叫组件的addActionListener()方法注册Listener。

三、UI标签的应用举例:

四.2实时事件

所谓的实时事件(Immediate
伊芙nts),是指JSF视图组件在获得请求中该获得的值之后,即登时处理钦定的轩然大波,而不再举行继续的调换器处理、验证器处理、更新模型值等工艺流程。

在JSF的事件模型中会有所谓实时事件,导致的原因于Web应用程序的后天特性不相同于GUI程序,所以JSF的轩然大波形式与
GUI程序的轩然大波方式仍有拾分程度的例外,三个最中央的主题素材正因为HTTP无状态的特征,使得Web应用程序天生就不可能直接唤起伺服端的特定对象。  所有的对象唤起都以在伺服端实行的,至于该唤起什么目的,则是依贰个中坚的流程:

•回复画面(Restore View)
  依客户端传来的session数据或伺服端上的session数据,回复JSF画面组件。

•套用请求值(Apply Request Values)
  JSF画面组件各自赢得请求中的值属于自个儿的值,蕴涵旧的值与新的值。

•施行验证(Process Validations)
  调换为目的并拓展认证。

•更新模型值(Update Model Values)
  更新Bean或相关的模型值。

•唤起应用程序(Invoke Application)
  实践应用程序相关逻辑。

•绘制回应画面(Render Response)
  对在此以前的呼吁处理完之后,爆发画面以响应客户端施行结果。

 

对此动作事件(Action
伊夫nt)来讲,组件的动作事件是在沿用请求值阶段就生成Action伊夫nt对象了,但有关的事件处理并不是随即举行,Action伊夫nt会先被排入队列,然后必须再经过认证、更新形式值阶段,之后才处理队列中的事件。

那般的流水生产线对于按下开关然后举办后端的应用程序来讲小意思,但稍事事件并不必要这样的流程,例如只影响画面包车型大巴轩然大波。

举个例子来讲,在窗体中或者有使用者名称、密码等字段,并提供有二个地点采取开关,使用者能够在不填下开关的情景下,就按下地面选用开关,要是依照符合规律的流水生产线,则会开始展览求证、更新模型值、唤起应用程序等工艺流程,但鲜明的,使用者名称与密码是空荡荡的,那会唤起不要求的一无是处。

你能够设定组件的事件在沿用请求值之后随即被处理,并跳过继续的级差,直接进行画面绘制以响应请求,对于JSF的input与command组件,都有3个immediate属性能够设定,只要将其设定为true,则钦定的风浪就改为当时事件。三个例证如下:

index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=UTF8"%>
<f:view locale="#{user.locale}">
<f:loadBundle basename="messages" var="msgs"/>

<html>
<head>
<title><h:outputText value="#{msgs.titleText}"/></title>
</head>
<body>

<h:form>
<h3><h:outputText value="#{msgs.hintText}"/></h3>
<h:outputText value="#{msgs.nameText}"/>:
<h:inputText value="#{user.name}"/><p>
<h:outputText value="#{msgs.passText}"/>:
<h:inputSecret value="#{user.password}"/><p>
<h:commandButton value="#{msgs.commandText}"
action="#{user.verify}"/>
<h:commandButton value="#{msgs.Text}"
immediate="true"
actionListener="#{user.changeLocale}"/>
</h:form>
</body>
</html>
</f:view>

  

那是一个足以让使用者决定选择语系的演示,最终一个commandButton组件被设定了immediate属性,当按下这些开关后,JSF
套用请求值之后会及时处理钦定的actionListener,而不再进行求证、更新模型值,简来讲之,就以此顺序来说,您在输入字段与密码字段中填入的
值,不会影响你的user.name与user.password。基于范例的完好起见,大家列出这一个程序Bean对象及faces-
config.xml:
UserBean.java

package onlyfun.caterpillar;

import javax.faces.event.ActionEvent;

public class UserBean {
private String locale = "en";
private String name;
private String password;
private String errMessage;

public void changeLocale(ActionEvent e) {
if(locale.equals("en"))
locale = "zh_TW";
else
locale = "en";
}

public String getLocale() {
if (locale == null) {
locale = "en";
}
return locale;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setPassword(String password) {
this.password = password;
}

public String getPassword() {
return password;
}

public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}

public String getErrMessage() {
return errMessage;
}

public String verify() {
if(!name.equals("justin") ||
!password.equals("123456")) {
errMessage = "名称或密码错误";
return "failure";
}
else {
return "success";
}
}
}

 

faces-config.xml

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<navigation-rule>
<from-view-id>/pages/index.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/pages/welcome.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/pages/index.jsp</to-view-id>
</navigation-case>
</navigation-rule>

<managed-bean>
<managed-bean-name>user</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.UserBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

 

音信托投财富文件的剧情则是之类:

messages_en.properties

titleText=JSF Demo
hintText=Please input your name and password
nameText=name
passText=password
commandText=Submit
Text=\u4e2d\u6587

  

Text中设定的是「中文」调换为Java Unicode
Escape格式的结果,另三个新闻能源文件的内容则是英文音信的翻译而已,其转移为Java
Unicode Escape格式结果如下:

messages_zh_TW.properties

titleText=JSF\u793a\u7bc4
hintText=\u8acb\u8f38\u5165\u540d\u7a31\u8207\u5bc6\u78bc
nameText=\u540d\u7a31
passText=\u5bc6\u78bc
commandText=\u9001\u51fa
Text=English

 

welcome.jsp就请自行设计了,程序的画面如下:

三.一、<h:form>和基本输入标签的利用:

4.3值变事件

假如使用者改造了JSF输入组件的值后送出窗体,就会时有爆发值变事件(Value
Change伊芙nt),那会丢出3个javax.faces.event.ValueChange伊夫nt对象,若是你想要处理这一个事件,有二种形式,一是向来 设定JSF输入组件的valueChangeListener属性,例如:

<h:selectOneMenu value="#{user.locale}"
onchange="this.form.submit();"
valueChangeListener="#{user.changeLocale}">
<f:selectItem itemValue="zh_TW" itemLabel="Chinese"/>
<f:selectItem itemValue="en" itemLabel="English"/>
</h:selectOneMenu>

  

为了仿真GUI中选取了选单项目然后就立时发生反应,我们在onchange属性中利用了JavaScript,其职能是在挑选项目暴发转移之
后,立即送出窗体,而不用按下交给按键;而valueChangeListener属性所绑定的user.changeLocale方法必须承受
ValueChange伊夫nt对象,例如:
UserBean.java

package onlyfun.caterpillar;

import javax.faces.event.ValueChangeEvent;

public class UserBean {
private String locale = "en";
private String name;
private String password;
private String errMessage;

public void changeLocale(ValueChangeEvent event) {
if(locale.equals("en"))
locale = "zh_TW";
else
locale = "en";
}

public void setLocale(String locale) {
this.locale = locale;
}

public String getLocale() {
if (locale == null) {
locale = "en";
}
return locale;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setPassword(String password) {
this.password = password;
}

public String getPassword() {
return password;
}

public void setErrMessage(String errMessage) {
this.errMessage = errMessage;
}

public String getErrMessage() {
return errMessage;
}

public String verify() {
if(!name.equals("justin") ||
!password.equals("123456")) {
errMessage = "名称或密码错误";
return "failure";
}
else {
return "success";
}
}
}

  

另三个办法是实作javax.faces.event.ValueChangeListener接口,并定义其processValueChange()方法,例如:
SomeListener.java

package onlyfun.caterpillar;
public class SomeListener implements ValueChangeListener {
public void processValueChange(ValueChangeEvent event) {
}
}

  

接下来在JSF页面上运用<f:valueChangeListener>卷标,并设定其type属性,例如:

{code:borderStyle=solid}
<h:selectOneMenu value="#{user.locale}"
onchange="this.form.submit();">
<f:valueChangeListener
type="onlyfun.caterpillar.SomeListener"/>
<f:selectItem itemValue="zh_TW" itemLabel="Chinese"/>
<f:selectItem itemValue="en" itemLabel="English"/>
</h:selectOneMenu>

  

下边这几个页面是对 霎时事件
中的范例程序作三个修改,将语言选用改以下拉式选单的采纳方式显示,那无法不合营地点提供的UserBean种类来使用:
index.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@page contentType="text/html;charset=UTF8"%>

<f:view locale="#{user.locale}">
<f:loadBundle basename="messages" var="msgs"/>

<html>
<head>
<title><h:outputText value="#{msgs.titleText}"/></title>
</head>
<body>

<h:form>
<h:selectOneMenu value="#{user.locale}"
immediate="true"
onchange="this.form.submit();"
valueChangeListener="#{user.changeLocale}">

<f:selectItem itemValue="zh_TW"
itemLabel="Chinese"/>
<f:selectItem itemValue="en"
itemLabel="English"/>
</h:selectOneMenu>

<h3><h:outputText value="#{msgs.hintText}"/></h3>
<h:outputText value="#{msgs.nameText}"/>:
<h:inputText value="#{user.name}"/><p>
<h:outputText value="#{msgs.passText}"/>:
<h:inputSecret value="#{user.password}"/><p>
<h:commandButton value="#{msgs.commandText}"
action="#{user.verify}"/>
</h:form>

</body>
</html>

</f:view>

<f:view>
    <h1>表单标签</h1>
    <h:form>
        单行文本框:<h:inputText value="#{userbean.username }" /><br />
        密码框:<h:inputSecret value="#{userbean.password }" /><br />
        多行文本区:<h:inputTextarea rows="3" cols="20" /><br />
        隐藏域:<h:inputHidden value="#{userbean.message }" /><br />
    </h:form>
</f:view>

4.4 Phase事件

在实时事变 中我们关系,JSF的伏乞实施到响应,完整的经过会经过三个阶段:

l  回复画面(Restore View)
  依客户端传来的session数据或伺服端上的session数据,回复JSF画面组件。

l  套用请求值(Apply Request Values)
  JSF画面组件各自赢得请求中的值属于本身的值,包含旧的值与新的值。

l  施行验证(Process Validations)
  转变为目的并开始展览表明。

l  更新模型值(Update Model Values)
  更新Bean或有关的模型值。

l  唤起应用程序(Invoke Application)
  试行应用程序相关逻辑。

l  绘制回应画面(Render Response)
  对原先的请求处理完之后,发生画面以响应客户端施行结果。

在各类阶段的上下会引发javax.faces.event.Phase伊芙nt,假使你想尝试在各类阶段的左右捕捉
这一个事件,以拓展1些处理,则能够实作javax.faces.event.PhaseListener,并向
javax.faces.lifecycle.Lifecycle
登记这几个Listener,以有万分的时候公告事件的发生。

PhaseListener有多少个必须实作的措施getPhaseId()、beforePhase()与afterPhase(),个中getPhaseId()传回贰个PhaseId对象,代表Listener想要被打招呼的机遇,能够设定的空子有:

• PhaseId.RESTORE_VIEW
• PhaseId.APPLY_REQUEST_VALUES
• PhaseId.PROCESS_VALIDATIONS
• PhaseId.UPDATE_MODEL_VALUES
• PhaseId.INVOKE_APPLICATION
• PhaseId.RENDER_RESPONSE
• PhaseId.ANY_PHASE

  

其中PhaseId.ANY_PHASE指的是其他的级差转变时,就进行通报;您能够在beforePhase()与afterPhase()中作文阶段前后撰写分别想要处理的动作,例如下边那些简单的档次会列出各类阶段的称谓:
ShowPhaseListener.java

package onlyfun.caterpillar;

import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

public class ShowPhaseListener implements PhaseListener {

public void beforePhase(PhaseEvent event) {
String phaseName = event.getPhaseId().toString();
System.out.println("Before " + phaseName);
}

public void afterPhase(PhaseEvent event) {
String phaseName = event.getPhaseId().toString();
System.out.println("After " + phaseName);
}

public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}

  

作文好PhaseListener后,大家得以在faces-config.xml中向Lifecycle实行登记:
faces-config.xml

<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
<lifecycle>
<phase-listener>
onlyfun.caterpillar.ShowPhaseListener
</phase-listener>
</lifecycle>
</faces-config>

  

你能够动用那些差不多的花色,看看在呼吁任2个JSF画面时所出示的始末,藉此驾驭JSF每一种阶段的流程变化。

当中<h:inputText>和<h:inputSecret>可以钦赐三个size属性用于钦赐输入框的最大尺寸。

5. JSF 标签

网页设计职员要作的正是领悟JSF的价签的施用格局,那就像学习进阶的HTML标签,另1件事正是与程序设计职员关系好各类Bean的称呼绑定。卷标的连锁属性查询,您能够参考
Tag LibraryDocumentation,那边的介绍只是部分归纳的入门实例。

叁.二、多选标签的施用:

5.1简要介绍JSF标准标签

JSF提供了正规化的HTMLRenderer
Kit,能够让你搭配JSF组件输出HTML文件,标准的HTML Renderer
Kit主要包蕴了多少个品类:

l  输出(Outputs)
  其名目以output作为初步,功效为出口钦点的资源信息或绑定值。

l  输入(Inputs)
  其名称以input作为初步,其功能为提供使用者输入字段。

l  命令(Commands)
  其名目以command作为早先,其效能为提供命令或连结按键。

l  选择(Selections)
  其名目以select作为起先,其功效为提供使用者选项的抉择。

l  其它
  包含了form、message、messages、graphicImage等等未分类的标签。

JSF标准HTML标签包罗了多少个共通的习性,整理如下:

属性名称

适用

说明

id

所有组件

可指定id名称,以让其它卷标或组件参考

binding

所有组件

绑定至UIComponent

rendered

所有组件

是否显示组件

styleClass

所有组件

设定Cascading stylesheet (CSS)

value

输入、输出、命令组件

设定值或绑定至指定的值

valueChangeListener

输入组件

设定值变事件处理者

converter

输入、输出组件

设定转换器

validator

输入组件

设定验证器

required

输入组件

是否验证必填字段

immediate

输入、命令组件

是否为立即事件

  

除开共通的性质之外,您还可以够在好几零部件上设定卷标HTML
肆.0壹的习性,像是size、alt、width等天性,可能是设定DHTML事件性质,例如onchange、onclick等等。

除此而外JSF的科班HTML标签之外,您还需求有的标准基本卷标,这一个卷标是单身于Renderer
基特的,JSF并不限量在HTML输出表示层,大旨标签能够搭配其余的Renderer
Kit来利用。详细的HTML卷标或主题卷标的行使与性情表明能够查询Tag Library
Documentation

文件。

<h1>多选标签的使用</h1>
<h:form>
    <!-- 复选框 -->
    <h:selectManyCheckbox value="#{userbean.booklist }">
        <f:selectItem itemLabel="Core Java" itemValue="Java" />
        <f:selectItem itemLabel="Thinking in C++" itemValue="C++" />
        <f:selectItem itemLabel="Spring Internals" itemValue="Spring" />
    </h:selectManyCheckbox>

    <!-- 生成一个允许多选的列表框 -->
    <h:selectManyListbox value="#{userbean.booklist }" size="5">
        <f:selectItem itemLabel="Core Java" itemValue="Java" />
        <f:selectItem itemLabel="Thinking in C++" itemValue="C++" />
        <f:selectItem itemLabel="Spring Internals" itemValue="Spring" />
    </h:selectManyListbox>

    <!-- 生成一个允许多选的复合框 -->
    <h:selectManyMenu value="#{userbean.booklist }">
        <f:selectItem itemLabel="Core Java" itemValue="Java" />
        <f:selectItem itemLabel="Thinking in C++" itemValue="C++" />
        <f:selectItem itemLabel="Spring Internals" itemValue="Spring" />
    </h:selectManyMenu>
</h:form>

5.贰出口类标签

输出类的标签包蕴了outputLabel、outputLink、outputFormat与
outputText,分别举例表明如下:

l  outputLabel

发生<label>HTML卷标,使用for属性内定组件的client ID,例如:

<h:inputText id="user" value="#{user.name}"/>

<h:outputLabel for="user" value="#{user.name}"/>

 

那会生出像是以下的价签:

<input id="user" type="text" name="user" value="guest" />

<label for="user">

 

l  outputLink

产生<a>HTML标签,例如:

<h:outputLink value="../index.jsp">

    <h:outputText value="Link to Index"/>

    <f:param name="name" value="MyName"/>

</h:outputLink>

 

您可搭配<f:param>帮链接加上参数,全数的参数都会化为 name=value
的型态附加在联网后。value所钦点的内容也得以是JSFEL绑定。

 

l  outputFormat

产生钦赐的文字消息,能够搭配<f:param>来设定新闻的参数以格式化文字音讯,例如:

<f:loadBundle basename="messages" var="msgs"/>

 <h:outputFormat value="#{msgs.welcomeText}">

     <f:param value="Hello"/>

     <f:param value="Guest"/>

 </h:outputFormat>

 

设若您的messages.properties包括以下的内容:

welcomeText={0}, Your name is {1}.

 

则{0}与{1}会被代替他为<f:param>设定的文字,最后展现的文字会是:Hello,
Your name isGuest.

 

另3个选拔的法子则是:

<h:outputFormat value="{0}, Your name is {1}.">

     <f:param value="Hello"/>

     <f:param value="Guest"/>

 </h:outputFormat>

 

l  outputText

轻巧易行的显得钦命的值或绑定的情报,例如:

<h:outputText value="#{user.name}"/>

行使方面包车型大巴多少个标签必须与<f:selectItem>或然<f:selectItems>标签结合使用,其中的<f:selectItem>1本性格的意思:

伍.三输入类标签

输入类标签包含了inputText、inputTextarea、inputSecret、
inputHidden,分别举例表达如下:

l  inputText

体现单行输入字段,即出口<input>HTML卷标,其type属性设定为text,例如:

<h:inputText value="#{user.name}"/>

 

l  inputTextarea

呈现多行输入文字区域,即出口<textarea>HTML标签,例如:

<h:inputTextarea value="#{user.command}"/>

 

l  inputSecret

来得密码输入字段,即出口<input>HTML卷标,其type属性设定为password,例如:

<h:inputSecret value="#{user.password}"/>

 

您可以设定redisplay属性以调节是不是要出示密码字段的值,预设是false。

 

l  inputHidden

隐藏字段,即出口<input>
HTML卷标,其type属性设定为hidden,隐藏字段的值用于保留部分资源新闻于客户端,以在下叁遍发送窗体时一并送出,例如:

<h:inputHidden value="#{user.hiddenInfo}"/>

itemLabel:可视化标签值
itemValue:点名生成列表项也许复选框的值
value:与其余的UI标签的value属性分歧,不是将该器件的值绑定到托管Bean,而是将该器件自个儿绑定到托管Bean

伍.四下令类标签

指令类标签包蕴commandButton与commandLink,其利害攸关意义在于提供三个限令开关或连结,以下举例表达:

l  commandButton

  展现三个发令开关,即出口<input>
HTML卷标,其type属性能够设定为button、submit或reset,预设是submit,按下按键会触发javax.faces.event.Action伊芙nt,使用例子如下:

<h:commandButton value="送出" action="#{user.verify}"/>

  

你能够设定image属性,内定图片的UKoleosL,设定了image属性的话,<input>卷标的type属性会被设定为image,例如:

<h:commandButton value="#{msgs.commandText}"image="images/logowiki.jpg"

action="#{user.verify}"/>

l  commandLink

   产生一级链接,会输出<a>
HTML卷标,而href属性会有’#’,而onclick属性会含有1段JavaScript程序,那个JavaScript的目标是按下连着后自行提
交窗体,具体来讲其效果就好像开关,但外观却是一级链接,包含在本体部份的剧情都会变成一级链接的一部份,一个运用的例证如下:

<h:commandLink value="#{msgs.commandText}" action="#{user.verify}"/>

 

发出的HTML输出范例如下:

<a href="#" onclick="document.forms[‘_id3’][‘_id3:_idcl’].value=’_id3:_id13′; document.forms[‘_id3’].submit(); return false;">Submit</a>

 

要是搭配<f:param>来选择,则所设定的参数会被视作请求参数一并送出,例如:

<h:commandLink>

<h:outputText value="welcome"/>

   <f:param name="locale" value="zh_TW"/>

</h:commandLink>

那多少个标签的value属性值必须是一个List恐怕数组。

5.5取舍类标签

接纳类的价签可略分为单选卷标与多选卷标,依外型的两样足以分成单选钮(Radio)、复选框(Check博克斯)、列示方块(ListBox)与
选单(Menu),以下分别先作简来说之明。<h:selectBooleanCheckbox>在视图上显现多少个复选框,例如:

<h:selectBooleanCheckbox value="#\{user.aggree\}"/>

 

value所绑定的属性必须承受与传播boolean型态。这么些组件在网页上表现的外观如下:

<h:selectOneRadio>、<h:selectOneListbox>、<h:
selectOneMenu>那多少个标签的效能,是让使用者从其所提供的选项中精选一个品类,所不相同的正是其外观上的异样,例如:

<h:selectOneRadio value="#{user.education}">
<f:selectItem itemLabel="高中" itemValue="高中"/>
<f:selectItem itemLabel="大学" itemValue="大学"/>
<f:selectItem itemLabel="研究所以上" itemValue="研究所以上"/>
</h:selectOneRadio>

 

value所绑定的性情能够承受字符串以外的型态或是自订型态,但记得如若是必须改动的型态或自订型态,必须搭配标准转变器
或 自订转换器 来转变为对象,<h:selectOneRadio>的外观如下:

你也得以设定layout属性,可设定的性质是lineDirection、pageDirection,预设是lineDirection,也正是由左到右来排列选项,假若设定为pageDirection,则是贯穿排列选项,例如设定为:

<h:selectOneRadio layout="pageDirection" value="#{user.education}">
<f:selectItem itemLabel="高中" itemValue="高中"/>
<f:selectItem itemLabel="大学" itemValue="大学"/>
<f:selectItem itemLabel="研究所以上" itemValue="研究所以上"/>
</h:selectOneRadio>

 

则外观如下:

<h:selectOneListbox>、<h:selectOneMenu>的设定方法类似于<h:
selectOneRadio>,以下分别列出<h:selectOneListbox>、<h:
selectOneMenu>的外观:

<h:selectManyCheckbox>、<h:selectManyListbox>、<h:
selectManyMenu>那八个卷标提供使用者复选项指标效率,3个<h:selectManyCheckbox>例子如下:

<h:selectManyCheckbox layout="pageDirection" value="#{user.preferColors}">
<f:selectItem itemLabel="红" itemValue="false"/>
<f:selectItem itemLabel="黄" itemValue="false"/>
<f:selectItem itemLabel="蓝" itemValue="false"/>
</h:selectManyCheckbox>

 

value所绑定的性格必须是数组或集合(Collection)对象,在这些事例中所使用的是boolean数组,例如:
UserBean.java

package onlyfun.caterpillar;
public class UserBean {
private boolean[] preferColors;
public boolean[] getPreferColors() {
return preferColors;
}
public void setPreferColors(boolean[] preferColors) {
this.preferColors = preferColors;
}
}

 

倘要是其它型态的对象,要求时必须搭配调换器(Converter)进行字符串与目的之间的转移。

 

下图是<h:selectManyCheckbox>的外观,那是将layout设定为pageDirection的外观:  <h:selectManyListbox>的设定方法类似,其外观如下:

<h:selectManyMenu>在区别的浏览器中会有不一致的外观,在Mozilla
Firefox中是这么的:

在InternetExplorer则是那样的:

 

选拔类标签能够搭配<f:selectItem>或<f:selectItems>卷标来设定选项,例如:

<f:selectItem itemLabel="高中"
itemValue="高中"
itemDescription="学历"
itemDisabled="true"/>

 

itemLabel属性设定显示在网页上的文字,itemValue设定发送至伺服端时的值,itemDescription
设定文字描述,它只效劳于某个工具程序,对HTML未有啥样震慑,itemDisabled设定是或不是采用是还是不是作用,那些属性也都能够行使JSF
ExpressionLanguage来绑定至3个值。<f:selectItem>也足以动用value来绑定一个传播
javax.faces.model.SelectItem的法子,例如:

<f:selectItem value="#{user.sex}"/>

 

则绑定的Bean上必须提供上边这么些点子:

public SelectItem getSex() {
return new SelectItem("男");
}

 

假定要贰回提供两个选择,则足以采用<f:selectItems>,它的value绑定至多个提供传回SelectItem的数组、集合,大概是Map对象的方法,例如:

<h:selectOneRadio value="#{user.education}">
<f:selectItems value="#{user.educationItems}"/>
</h:selectOneRadio>

 

那么些事例中<f:selectItems>的value绑定至user.educationItems,其剧情如下:

private SelectItem[] educationItems;

public SelectItem[] getEducationItems() {
if(educationItems == null) {
educationItems = new SelectItem[3];
educationItems[0] =
new SelectItem("高中", "高中");
educationItems[1] =
new SelectItem("大学", "大学");
educationItems[2] =
new SelectItem("研究所以上", "研究所以上");
}
return educationItems;
}

 

在这么些例子中,SelectItem的首先个建构参数用以设定value,而第三个参数用以设定label,SelectItem还提供有数个建构函式,记得能够参考一下线上API文件。

您也能够提供三个传回Map对象的点子,Map的key-value会分别作为挑选的label-value,例如:

<h:selectManyCheckbox layout="pageDirection"  value="#{user.preferColors}">
<f:selectItems value="#{user.preferColorItems}"/>
</h:selectManyCheckbox>

 

您要提供下边包车型大巴次第来搭配上边那几个事例:

private Map preferColorItems;

public Map getPreferColorItems() {
if(preferColorItems == null) {
preferColorItems = new HashMap();
preferColorItems.put("红", "Red");
preferColorItems.put("黄", "Yellow");
preferColorItems.put("蓝", "Blue");
}
return preferColorItems;
}

3.三、单选标签的行使:

五.6任何标签

<h:messages>或<h:message>标签的牵线,在错误新闻处理中早就有介绍了。

l  <h:graphicImage>

本条卷标会绘制叁个HTML
<img>卷标,value能够钦命路径或图片U酷路泽L,路线能够钦命相对路径或相对路线,例如:

<h:graphicImage value="logowiki.jpg"/>
<h:panelGrid>

  那一个卷标能够用来作轻易的零件排版,它会采纳HTML表格卷标来绘制表格,并将零件置于个中,首要钦点columns属性,例如设定为
二:

<h:panelGrid columns="2">
<h:outputText value="Username"/>
<h:inputText id="name" value="#{userBean.name}"/>
<h:outputText value="Password"/>
<h:inputText id="password" value="#{userBean.password}"/>
<h:commandButton value="submit" action="login"/>
<h:commandButton value="reset" type="reset"/>
</h:panelGrid>

 

则自动将零件分作 贰 个 column来排列,排列出来的旗帜如下:

 

<h:panelGrid>的本体间只可以包含JSF组件,假如想要放入非JSF组件,例如轻易的样版(template)文字,则要使用
<f:verbatim>包罗住,例如:

<h:panelGrid columns="2">
<f:verbatim>Username</f:verbatim>
<h:inputText id="name" value="#{userBean.name}"/>
<f:verbatim>Password</f:verbatim>
<h:inputText id="password" value="#{userBean.password}"/>
<h:commandButton value="submit" action="login"/>
<h:commandButton value="reset" type="reset"/>
</h:panelGrid>
<h:panelGroup>

 

本条组件用来将数个JSF组件包装起来,使其看来像是3个零部件,例如:

<h:panelGrid columns="2">
<h:outputText value="Username"/>
<h:inputText id="name" value="#{userBean.name}"/>
<h:outputText value="Password"/>
<h:inputText id="password" value="#{userBean.password}"/>
<h:panelGroup>
<h:commandButton value="submit" action="login"/>
<h:commandButton value="reset" type="reset"/>
</h:panelGroup>
</h:panelGrid>

 

在<h:panelGroup>中回顾了七个<h:commandButton>,那使得<
h:panelGrid>在处理时,将那八个<h:commandButton>看作是3个零件来对待,其成功的版面布置如下所示:

<h1>单选标签的使用</h1>
<h:form>
    <!-- 生成一组单选按钮 -->
    <h:selectOneRadio value="userbean.booklist">
        <f:selectItem itemLabel="Core Java" itemValue="Java" />
        <f:selectItem itemLabel="Thinking in C++" itemValue="C++" />
        <f:selectItem itemLabel="Spring Internals" itemValue="Spring" />
    </h:selectOneRadio>
    <!-- 生成一个只允许单选的列表框 -->
    <h:selectOneListbox value="userbean.booklist" size="5">
        <f:selectItem itemLabel="Core Java" itemValue="Java" />
        <f:selectItem itemLabel="Thinking in C++" itemValue="C++" />
        <f:selectItem itemLabel="Spring Internals" itemValue="Spring" />
    </h:selectOneListbox>
    <!-- 生成一个只允许单选的下来菜单 -->
    <h:selectOneMenu value="#{userbean.booklist }">
        <f:selectItem itemLabel="Core Java" itemValue="Java" />
        <f:selectItem itemLabel="Thinking in C++" itemValue="C++" />
        <f:selectItem itemLabel="Spring Internals" itemValue="Spring" />
    </h:selectOneMenu>
</h:form>

陆. 报表处理

对于必须利用表格形式呈现的数据,JSF 的 <h:dataTable>
卷标协理您举行动态表格数据的输出。

那多少个标签和方今介绍的多少个标签的遵循大旨相似,只是那里的只可以单选。

6.壹粗略的报表

过大多目经常选取表格来显示,JSF提供<h:dataTable>卷标让你能够列举数据并应用表格情势来显现,举个实际的事例来看,假诺您撰写了以下的多少个类型:

UserBean.java

package onlyfun.caterpillar;

public class UserBean {
private String name;
private String password;

public UserBean() {
}

public UserBean(String name, String password) {
this.name = name;
this.password = password;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}

 

TableBean.java

package onlyfun.caterpillar;
import java.util.*;
public class TableBean {
private List userList;

public List getUserList() {
if(userList == null) {
userList = new ArrayList();
userList.add(new UserBean("caterpillar", "123456"));
userList.add(new UserBean("momor", "654321"));
userList.add(new UserBean("becky", "7890"));
}

return userList;
}
}

  在TableBean中,大家借使getUserList()方法其实是从数据库中询问出UserBean的剧情,之后传出List对象,若大家的
faces-config.xml如下:
faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems,
Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">

<faces-config>
<managed-bean>
<managed-bean-name>tableBean</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.TableBean
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.UserBean
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>

  

咱俩得以如下使用<h:dataTable>来发出表格数据:
index.jsp

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<body>
<f:view>
<h:dataTable value="#{tableBean.userList}" var="user">
<h:column>
<h:outputText value="#{user.name}"/>
</h:column>
<h:column>
<h:outputText value="#{user.password}"/>
</h:column>
</h:dataTable>
</f:view>
</body>
</html>

 

<h:dataTable>的value值绑定tableBean的userList方法,它会叁个贰个抽取List中的数据并设定给var设定的user,之后在每三个column中大家得以体现所列举出的user.name与user.password,程
序的结果会如下所示:

所发生的HTML表格卷标如下:

<table>
<tbody>
<tr>
<td>caterpillar</td>
<td>123456</td>
</tr>
<tr>
<td>momor</td>
<td>654321</td>
</tr>
<tr>
<td>becky</td>
<td>7890</td>
</tr>
</tbody>
</table>

 

  <h:dataTable>的value值绑定的指标能够是以下的型态:
• 数组
•java.util.List的实例
•java.sql.ResultSet的实例
•javax.servlet.jsp.jstl.sql.Result的实例
•javax.faces.model.DataModel的实例

叁.四、UISelectBoolean组件的施用:

6.二表头和表尾

<h:dataTable>合作<h:column>来以表格的主意浮现数据,<
h:column>中只好包罗JSF组件或然是<f:facet>,JSF支援二种facet:header与footer。分别用于
设定表格的表头与表尾文字,贰个设定的例证如下:

<h:dataTable value="#{tableBean.userList}" var="user">
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{user.name}"/>
<f:facet name="footer">
<h:outputText value="****"/>
</f:facet>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Password"/>
</f:facet>
<h:outputText value="#{user.password}"/>
<f:facet name="footer">
<h:outputText value="****"/>
</f:facet>
</h:column>
</h:dataTable>

 

所发生的报表如下所示:

其它,对于表头、表尾仍至于每一连串,都足以分级设定CSS风格,例如下边这几个styles.css摘录自Core
JSF1书:
styles.css

.orders {
border: thin solid black;
}

.ordersHeader {
text-align: center;
font-style: italic;
color: Snow;
background: Teal;
}

.evenColumn {
height: 25px;
text-align: center;
background: MediumTurquoise;
}

.oddColumn {
text-align: center;
background: PowderBlue;
}

  

能够在大家的页面中如下参加:

<link href="styles.css" rel="stylesheet" type="text/css"/>
<h:dataTable value="#{tableBean.userList}" var="user"
styleClass="orders"
headerClass="ordersHeader"
rowClasses="evenColumn,oddColumn">
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:outputText value="#{user.name}"/>
<f:facet name="footer">
<h:outputText value="****"/>
</f:facet>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Password"/>
</f:facet>
<h:outputText value="#{user.password}"/>
<f:facet name="footer">
<h:outputText value="****"/>
</f:facet>
</h:column>
</h:dataTable>

 

则展现的表格结果如下:

<h:selectBooleanCheckbox />

6.3TableModel 类别

在简易的报表中曾经提过,<h:dataTable>能够列举以下二种型态的多寡:
• 数组
•java.util.List的实例
•java.sql.ResultSet的实例
•javax.servlet.jsp.jstl.sql.Result的实例
•javax.faces.model.DataModel的实例
  

对从前八种型态,JSF实际上是以javax.faces.model.DataModel加以包装,DataModel是个抽象种类,其子连串都以坐落
javax.faces.model这么些package下:
•ArrayDataModel
•ListDataModel
•ResultDataModel
•ResultSetDataModel
•ScalarDataModel
  

若是您想要对表格数据有越多的决定,您能够平昔运用DataModel来设定表格数据,呼叫DataModel的setWrappedObject()方法能够让你设定对应型态的多少,呼叫getWrappedObject()则足以取回数据,例如:
TableBean.java

package onlyfun.caterpillar;

import java.util.*;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

public class TableBean {
private DataModel model;
private int rowIndex = -1;

public DataModel getUsers() {
if(model == null) {
model = new ListDataModel();
model.setWrappedData(getUserList());
}

return model;
}

private List getUserList() {
List userList = new ArrayList();
userList.add(new UserBean("caterpillar", "123456"));
userList.add(new UserBean("momor", "654321"));
userList.add(new UserBean("becky", "7890"));

return userList;
}

public int getSelectedRowIndex() {
return rowIndex;
}

public String select() {
rowIndex = model.getRowIndex();
return "success";
}
}

 

在这么些Bean中,大家向来设定DataModel?,将userList设定给它,如你所观望的,大家还足以获取DataModel?的壹一变
项,在这么些事例中,select()将作为点选表格之后的事件处理方法,大家得以藉由DataModel?的getRowIndex
()来得到所点选的是哪1row的材质,例如:
index.jsp

 

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<link href="styles.css" rel="stylesheet" type="text/css"/>
<body>
<f:view>
<h:form>
<h:dataTable value="#{tableBean.users}" var="user"
styleClass="orders"
headerClass="ordersHeader"
rowClasses="evenColumn,oddColumn">
<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:commandLink action="#{tableBean.select}">
<h:outputText value="#{user.name}"/>
</h:commandLink>

<f:facet name="footer">
<h:outputText value="****"/>
</f:facet>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Password"/>
</f:facet>
<h:outputText value="#{user.password}"/>
<f:facet name="footer">
<h:outputText value="****"/>
</f:facet>
</h:column>
</h:dataTable>
</h:form>
Selected Row: <h:outputText
value="#{tableBean.selectedRowIndex}"/>
</f:view>
</body>
</html>

 

  DataModel的rowIndex是从0起先计算,当处理Action伊夫nt时,JSF会逐次递增rowIndex的值,那让你能够查出近来正值处理的是哪多个row的数码,2个举办的图示如下:

在页面上生成一个复选框,用于勾选大概吊销勾选该复选框

七. 自订组件

JSF
让你能够自订组件,每一个组件都是可替换的,那使得组件在搭配时更有弹性,但针锋相对的却使开荒组件的进度复杂的多,那边对自订JSF
组件只是个入门砖,愈多关于自订组件的底细可得要专书来表明。要耗费 JSF
组件,您要求更通透到底领会JSF的有些处理细节,蕴含了JSF生命周期以及JSF框架。

与地点七个复选框区别,它的value属性必须绑定到托管Bean中boolean类型的习性,不供给与<f:selectItem>标签一同使用。

7.一 JSF生命周期

JSF的每一个组件基本上都以可替换的,像是转变器(Converter)、验证器(Validator)、组件
(Component)、绘制器
(Renderer)等等,各个组件都得以轮换让JSF在利用时更有弹性,但针锋相对的所付出的就是组件组合时的复杂,为此,最中央的,如若您打算自订1些
JSF组件,那么你对于JSF处理请求的种种阶段必须要有所领悟。

下图是JSF处理请求时的各种阶段与简便表明,起头状态即便用者端发出请求时,终止意况则一定于绘制器发出响应时:

 

扣除事件处理,JSF总共必须经过七个级次:

l  回复画面(Restore View)

对此选择的页面假若是初次浏览则树立新的机件树。借使是会话阶段,会从使用者端或劳动器端的数额寻找数据以回复每种组件的事态仁同一视建组件树,假诺不包蕴请求参数,则一直跳过接下去的品级直接绘制响应。

l  套用申请值(Apply Request Values)

各样组件尝试一贯到的请求中找出本人的参数并更新组件值,在那边会触发Action伊夫nt,这些事件会被排入队列中,然后在引起应用程序阶段之后才会真正由事件处理者实行拍卖。

 

不过对于设定immeduate为true的命令(Commamnd)组件来讲,会及时处管事人件并跳过之后的阶段直接绘制响应,而对于设定immediate为true的输入(Input)组件,会立马开始展览转变验证并处理值变事件,之后跳过接下去的阶段,间接绘制响应。

l  实行验证(Process Validations)
   
实行转移与认证处理,假设证实错误,则会跳过之后的级差,间接绘制响应,结果是再度呼叫同壹页绘制结果。

l  更新模型值(Update Model Values)
  更新每三个与组件绑定的backingbean或模型对象。

l  唤起应用程序(Invoke Application)
  处理动作事件,并张开后端应用程序逻辑。

l  绘制回应(Render Response)
  使用绘制器绘制页面。

 

比方你只是要采用JSF,则您最基本的只必要精通推行验证、更新模型值与唤起应用程序那多个级次及中间的风云触发,JSF参考实作将那七个阶段之外的其他阶段之复杂隐藏起来了,您不需求知道那多少个级次的拍卖细节。

可是一旦您要自订组件,则您还必须精晓回复画面、套用请求值与绘图响应那一个等第是什么样处理的,那多少个等第十分复杂,所幸的是您能够应用JSF
所提供的框架来举办零部件自订,JSF提供的框架已经异常的大程度上下滑了组件制作的错综复杂。

理所当然,固然JSF框架降低了复杂,但其实要拍卖JSF自订组件照旧很复杂的一件事,在品尝开辟自订组件此前,您能够先搜寻一些网址,像是 Apache MyFaces
http://myfaces.apache.org/,看看是不是已经有相关类似的组件已经开发完成,省去您重新自订组件的气力。

3.伍、UICommand组件的运用:

七.二概述自订组件

所谓的自订JSF组件是一个大要的叫做,事实上,三个JSF组件包含了四个部份:Tag、Component
与Renderer。

Tag即从前一贯在使用的JSF卷标,类似于HTML卷标,JSF卷标主假如利于网页设计职员开始展览版面布署与数据显现的1种艺术,实际的处理中,JSF标签的目的在于设定Component属性、设定验证器、设定数据绑定、设定方法绑定等等。

Component的意在处理请求,当呼吁来到伺服端应用程序时,每八个Component都有空子依照自身的client
id,从呼吁中获取属于自身的值,接着Component能够将以此值作处理,然后设定给绑定的bean。

当呼吁来到Web应用程序时,HTTP中的字符串内容能够转移为JSF组件所需的值,那些动作称为译码
(decode),相对的,将JSF
组件的值转变为HTTP字符串数据并送至客户端,那个动作称为编码(encode),Component可自身处理编码、译码的职分,也能够将之委托给
Renderer来处理。

当你要自订Component时,您能够承袭UIComonent或其有关的子种类,那要依据你实际要自订的组件而定,
假如您要自订二个出口元
件,可以继承UIOutput,假如要自订一个输入组件,则可以承袭UIInput,每3个正规的JSF组件实际上都对应了一个UIComponent的子连串,下图为二个差不多的档次承继架构图:
   实际上要自订三个零件是错综复杂的一件职业,您首先要学会的是八个完好的自订组件流程,实际上要自订2个零部件时,您能够参见一下互联网上的有的产品,例如
Apache MyFaces http://myfaces.apache.org/
,接下去后边的多少个主题所要介绍的,将只是贰个自订组件的简约流程。

Renderer是2个可替换的零部件,您的Component能够搭配分化的Renderer,而不用自行担任绘制响应
或译码的动作,那会让您的
Component能够引用,当你必要将响应从HTML转变为任何的媒介时(例如行动电话网络),则只要替换Renderer就可以了,那是贰个便宜,只怕您能够大约的交替掉一个Renderer,就能够将原本轻巧的HTML响应,替换为有JavaScript功用的Renderer。

当您开首接触自订组件时,您会发轫接触到JSF的框架(Framework),大概有多少个项目会是你日常接触的:

•javax.faces.component.UIComponent
  
自订Component所要承接的父连串,但一般,您是连续其子体系,例如UIInput、UIOutput等等。
•javax.faces.webapp.UIComponentTag
   
自订JSF标签所要承袭的父体系,承继它能够帮你省去过多JSF标签处理的底细。
•javax.faces.context.FacesContext
   包含了JSF相关的伸手音信,您可以由此它拿走请求对象或请求参数,大概是
javax.faces.application.Application物件。
•javax.faces.application.Application
  
包含了1个应用程序所共享的音讯,像是locale、验证器、转变器等等,您能够经过一些厂子方法
获得相关的信息。

<h1>UICommand组件的使用</h1>
<h:form>
    <!-- 生成一个可以提交表单的按钮 -->
    <h:commandButton value="点击" />
    <!-- 生成一个图片按钮 -->
    <h:commandButton image="images/01.jpg" />
    <!-- 生成一个可以提交表单的超链接 -->
    <h:commandLink value="提交表单" />
    <!-- 生成一个可以提交表单的图片链接 -->
    <h:commandLink shape="circle" coords="20,20,10">
        <img src="images/01.jpg" />
    </h:commandLink>
</h:form>

七.三简易实例

在不思虑组件有子组件的情事下,那边以实际的三个事例来表明开垦组件的历程,至于思考子组件的情状请参考专书介绍。

叁.陆、UIOutput对应的输出组件的施用:

7.3.一编码和译码

Component能够友善担当将目的数据编码为HTML文件或别的的输出文件,也足以将以此任务委托给
Renderer,那边先介绍的是让Component本身负担编码的动作。

那边器重的是介绍成功自订组件所不可不的流程,所以我们不规划太复杂的组件,那边将达成以下的零部件,那几个组件会有二个输入文字字段以及多少个送出开关:

你要承袭UIComponent或其子类别来自订Component,由于文字字段是多个输入字段,为了便利,您能够继承UIInput连串,那足以让您省去1些处理细节的素养,在继承UIComponent或其子种类后,与编码相关的要害有七个方
法:encodeBegin()、encodeChildren()和encodeEnd()。在那之中encodeChildren()是在包含子组件时必
须定义,Component假使它的
getRendersChildren()方法传回true时会呼叫encodeChildren()方法,预设上,
getRendersChildren()方法传回false。

是因为我们的自订组件卓越轻巧,所以将编码的动作写在encodeBegin()或是encodeEnd()都能够,大家这边是定义encodeBegin
()方法:

UITextWithCmd.java

package onlyfun.caterpillar;

import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

public class UITextWithCmd extends UIInput {
private static final String TEXT = ".text";
private static final String CMD = ".cmd";

public UITextWithCmd() {
setRendererType(null);
}

public void encodeBegin(FacesContext context)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = getClientId(context);

encodeTextField(writer, clientId);
encodeCommand(writer, clientId);
}

public void decode(FacesContext context) {
// …..
}

private void encodeTextField(ResponseWriter writer,
String clientId) throws IOException {
writer.startElement("input", this);
writer.writeAttribute("name", clientId + TEXT, null);

Object value = getValue();
if(value != null) {
writer.writeAttribute("value",
value.toString(), null);
}

String size = (String) getAttributes().get("size");
if(size != null) {
writer.writeAttribute("size", size, null);
}

writer.endElement("input");
}

private void encodeCommand(ResponseWriter writer,
String clientId) throws IOException {
writer.startElement("input", this);
writer.writeAttribute("type", "submit", null);
writer.writeAttribute("name", clientId + CMD, null);
writer.writeAttribute("value", "submit", null);
writer.endElement("input");
}
}

 

 在encodeBegin()方法中,我们收获ResponseWriter对象,那个目的能够协理您输出HTML卷
标、属性等,大家应用
getClientId()获得组件的id,那个id是各类组件的唯一识别,预设上只要您未有点名,则JSF会自动为你发出id值。

 接着我们独家对输入文字字段及送出钮作HTML标签输出,在输出时,大家将name属性设成clientId与八个字符串值的重组(即TEXT或CMD),那是为了有利于在译码时,取得相应name属性的呼吁值。

在encodeTextField中大家有呼叫getValue()方法,这么些点子是从UIOutput承接下来
的,getValue()
方法能够赢得Component的设定值,这几个值恐怕是静态的本性设定值,也恐怕是JSFExpression的绑定值,预设会先从组件的属性设定值开头找出,借使找不到,再从绑定值(ValueBinding对象)中找出,组件的属性值或绑定值的设定,是在定义Tag时要作的事。

编碥的部份计算来讲,是取得Component的值并作适当的HTML标签输出,再来大家看看译码的部份,那是概念在decode()方法中,将下边包车型客车内容插足至地点的类型定义中:

public void decode(FacesContext context) {
Map reqParaMap = context.getExternalContext().
getRequestParameterMap();
String clientId = getClientId(context);

String submittedValue =
(String) reqParaMap.get(clientId + TEXT);
setSubmittedValue(submittedValue);
setValid(true);
}

 

咱俩亟须先拿走RequestParameterMap,那么些Map对象中填入了全数客户端传来的乞请参数,
Component在这些法子中有机遇查询那一个请求参数中,是或不是有和好所想要赢得的多少,记得我们前面译码时,是将输入字段的name属性译码为
clientid加上1个字符串值(即TEXT设定的值),所以那时,大家品尝从RequestParameterMap中取得那么些请求值。

赢得请求值之后,您可以将数据藉由setSumittedValue()设定给绑定的bean,最后呼叫setValid()方法,这一个措施设定为
true时,表示组件正确的获得自个儿的值,未有其余的不当发生。

出于大家先不行使Renderer,所以在建构函式中,大家设定RendererType为null,表示我们不使用Renderer进行译码输出:

public UITextWithCmd() {
setRendererType(null);
}

 

  在大家的例证中,大家都是处理字符串对象,所以那边不需求转换器,要是你须求利用转变器,能够呼叫setConverter()方法加以设定,在不利用
Renderer的时候,Component要设定调换器来机关开始展览字符串与指标的转换。

<h1>UIOutput对应的输出组件的使用</h1>
<!-- 使用outputText标签输出国际化资源 -->
<h:outputText value="#{userInfo.username }" />
<!-- 使用outputText标签输出Bean属性 -->
<h:outputText value="#{userbean.username }" />
<!-- 生成Label标签 -->
<h:outputLabel value="#{userbean.username }" />
<!-- 生成超链接 -->
<h:outputLink value="http://www.itzhai.com">IT宅</h:outputLink>
<!-- 输出带占位符的国际化消息 -->
<h:outputFormat value="#{userInfo.message }">
    <f:param value="arthinking" />
</h:outputFormat>

柒.三.贰零件卷标

完了Component的自订,接下去要设定2个自订Tag与之对应,自订Tag的目标,在于设定
Component属性,获得Componenty型态,赚取Renderer型态值等;属性的设定包涵了设定静态值、设定绑定值、设定验证器等等。要自
订与Component对应的Tag,您能够承袭UIComponentTag,例如:

TextWithCmdTag.java

package onlyfun.caterpillar;

import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;

public class TextWithCmdTag extends UIComponentTag {
private String size;
private String value;

public String getComponentType() {
return "onlyfun.caterpillar.TextWithCmd";
}

public String getRendererType() {
return null;
}

public void setProperties(UIComponent component) {
super.setProperties(component);

setStringProperty(component, "size", size);
setStringProperty(component, "value", value);
}

private void setStringProperty(UIComponent component,
String attrName, String attrValue) {
if(attrValue == null)
return;

if(isValueReference(attrValue)) {
FacesContext context =
FacesContext.getCurrentInstance();
Application application =
context.getApplication();
ValueBinding binding =
application.createValueBinding(attrValue);
component.setValueBinding(attrName, binding);
}
else {
component.getAttributes().
put(attrName, attrValue);
}
}

public void release() {
super.release();
size = null;
value = null;
}

public String getSize() {
return size;
}

public void setSize(String size) {
this.size = size;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

  

先是看到那多少个方法:

public String getComponentType() {
return "onlyfun.caterpillar.TextWithCmd";
}

public String getRendererType() {
return null;
}

 

是因为我们的Component近期不行使Renderer,所以getRendererType()传回null值,而
getComponentType()在于让JSF取得这几个Tag所对应的Component,所传回的值在faces-config.xml中要有定
义,例如:

<component>
<component-type>
onlyfun.caterpillar.TextWithCmd
</component-type>
<component-class>
onlyfun.caterpillar.UITextWithCmd
</component-class>
</component>

 

藉由faces-config.xml中的定义,JSF能够查出
onlyfun.caterpillar.TextWithCmd的真的体系,而那样的定义方式很扎眼的,您能够天天换掉<component-
class>所对应的项目,也正是说,Tag所对应的Component是足以每天替换的。
  在设定Component属性值时,能够由component.getAttributes()获得Map对象,并将卷标属性值存入Map
中,那个Map对象能够在相应的Component中利用getAttributes()取得,例如在上二个大旨中的UITextWithCmd中可以如
下赚取存入Map的size属性:
UITextWithCmd.java

package onlyfun.caterpillar;
import java.io.IOException;
import java.util.Map;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
public class UITextWithCmd extends UIInput {
private void encodeTextField(ResponseWriter writer,
String clientId) throws IOException {
String size = (String) getAttributes().get("size");
if(size != null) {
writer.writeAttribute("size", size, null);
}
}
}

 

能够使用isValueReference()来测试是还是不是为JSF Expression
Language的绑定语法,要是是的话,则我们无法不建立ValueBinding对象,并设定值绑定:

private void setStringProperty(UIComponent component,
String attrName, String attrValue) {
if(attrValue == null)
return;

if(isValueReference(attrValue)) {
FacesContext context =
FacesContext.getCurrentInstance();
Application application =
context.getApplication();
ValueBinding binding =
application.createValueBinding(attrValue);
component.setValueBinding(attrName, binding);
}
else {
component.getAttributes().
put(attrName, attrValue);
}
}

 

假诺是value属性,记得在上1个宗旨中我们提过,从UIOutput承接下来的getValue()方法能够得到Component的value设定值,这些值或然是静态的属性设定值,也说不定是JSF
Expression的绑定值,预设会先从组件的性能设定值开首搜索,假设找不到,再从绑定值(ValueBinding对象)中寻找。

终极,我们必须提供自订Tag的tld檔:
textcmd.tld

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0"
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/web-jsptaglibrary_2_0.xsd">
<tlib-version>1.0</tlib-version>
<jsp-version>2.0</jsp-version>
<short-name>textcmd</short-name>
<uri>http://caterpillar.onlyfun.net/textcmd</uri>
<tag>
<name>textcmd</name>
<tag-class>onlyfun.caterpillar.TextWithCmdTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>size</name>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
</attribute>
</tag>
</taglib>

那边运用到了国际化财富,供给创立:

七.三.叁选择自订组件

在Component与Tag自订达成后,那边来探望怎么样运用它们,首先定义faces-config.xml:
faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems,
Inc.//DTD JavaServer Faces Config 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<faces-config>
<component>
<component-type>
onlyfun.caterpillar.TextWithCmd
</component-type>
<component-class>
onlyfun.caterpillar.UITextWithCmd
</component-class>
</component>
<managed-bean>
<managed-bean-name>someBean</managed-bean-name>
<managed-bean-class>
onlyfun.caterpillar.SomeBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

  

<component>中定义Component的型态与事实上的类型对应,在您于自订Tag中呼唤
getComponentType()方法所重临的值,就是探究<component-type>设定的值对应,并通过得知真正对应的
Component连串。

 

咱俩所创作的SomeBean测试项目如下:

SomeBean

package onlyfun.caterpillar;
public class SomeBean {
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

 

那边写二个回顾的网页来测试一下大家创作的自订组件:
index.jsp

<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="/WEB-INF/textcmd.tld" prefix="oc" %>
<html>
<link href="styles.css" rel="stylesheet" type="text/css"/>
<head>
<title></title>
</head>
<body>
<f:view>
<h:form>
Input data: <oc:textcmd size="10"
value="#{someBean.data}"/>
</h:form>
<h:outputText value="#{someBean.data}"/>
</f:view>
</body>
</html>

在faces-config.xml问价中加载国际化能源的配置:

7.3.4自订 Renderer

Component能够将译码、编码的动作交给Renderer,那让你的表现层技艺能够轻巧的抽换,大家能够将事先的自订组件的译码、编码动作移
出至
Renderer,可是是因为大家前边设计的Component是个不会细小略的机件,事实上,若是只是要新添多个Command在输入字段旁边,大家并不要求狼狈周章的自订二个新的组件,我们得以一向为输入字段退换一个自订的Renderer。要自订3个Renderer,您要持续
javax.faces.render.Renderer,大家的自订Renderer如下:
TextCmdRenderer.java

package onlyfun.caterpillar;

import java.io.IOException;
import java.util.Map;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;

public class TextCmdRenderer extends Renderer {
private static final String TEXT = ".text";
private static final String CMD = ".cmd";

public void encodeBegin(FacesContext context,
UIComponent component) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = component.getClientId(context);

encodeTextField(component, writer, clientId);
encodeCommand(component, writer, clientId);
}

public void decode(FacesContext context,
UIComponent component) {
Map reqParaMap = context.getExternalContext().
getRequestParameterMap();
String clientId = component.getClientId(context);

String submittedValue =
(String) reqParaMap.get(clientId + TEXT);
((EditableValueHolder) component).setSubmittedValue(
submittedValue);
((EditableValueHolder) component).setValid(true);
}

private void encodeTextField(UIComponent component,
ResponseWriter writer, String clientId)
throws IOException {
writer.startElement("input", component);
writer.writeAttribute("name", clientId + TEXT, null);

Object value = ((UIInput) component).getValue();
if(value != null) {
writer.writeAttribute("value",
alue.toString(), null);
}

String size =
(String) component.getAttributes().get("size");
if(size != null) {
writer.writeAttribute("size", size, null);
}

writer.endElement("input");
}

private void encodeCommand(UIComponent component,
ResponseWriter writer,
String clientId) throws IOException {
writer.startElement("input", component);
writer.writeAttribute("type", "submit", null);
writer.writeAttribute("name", clientId + CMD, null);
writer.writeAttribute("value", "submit", null);
writer.endElement("input");
}
}

 

本条自订的Renderer其译码、编码进程,与事先向来在Component中展开译码或编码进度是类似的,所例外的是在译码与编码的章程上,多
了UIComponent参数,代表所代理绘制的Component。接下来在自订Tag上,大家的TextWithCmdTag与事先核心所介绍的没什
么差距,只然而在getComponentType()与
getRendererType()方法上要修改一下:
TextWithCmdTag.java

package onlyfun.caterpillar;

import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;

public class TextWithCmdTag extends UIComponentTag {
private String size;
private String value;

public String getComponentType() {
return "javax.faces.Input";
}

public String getRendererType() {
return "onlyfun.caterpillar.TextCmd";
}
}

 

getComponentType()取得的是”javax.faces.Input”,它实在对应至UIInput种类,而
getRendererType()取回的是”onlyfun.caterpillar.TextCmd”,那会在faces-config.xml中定
义,以对应至实际的Renderer连串:
faces-config.xml

<faces-config>
<render-kit>
<renderer>
<component-family>
javax.faces.Input
</component-family>
<renderer-type>
onlyfun.caterpillar.TextCmd
</renderer-type>
<renderer-class>
onlyfun.caterpillar.TextCmdRenderer
</renderer-class>
</renderer>
</render-kit>
</faces-config>

 

为Component定义一个Renderer,必须由component family与renderer
type共同定义,那并简单掌握,因为贰个Component可以搭配不一致的Renderer,但它是属于同3个component
family,例如UIInput正是属于javax.faces.Input那个组件家族,而笔者辈为它定义2个新的Renderer。接下未产生的范例
能够取从前主旨介绍过的,我们就算尚未自订组件,但大家为UIInput置换了三个新的Renderer,这一个Renderer会在输入字段上投入贰个按键。假设您坚定不移使用此前自订的UITextWithCmd,则能够如下修改:
UITextWithCmd.java

package onlyfun.caterpillar;

import javax.faces.component.UIInput;

public class UITextWithCmd extends UIInput {
public UITextWithCmd() {
setRendererType("onlyfun.caterpillar.TextCmd");
}
}

 

小编们只是单纯的承接UIInput,然后利用setRendererType()设
定”onlyfun.caterpillar.TextCmd”,但并从未为组件参与什么表现,看来什么事都并未有作,但实质上那是因为延续了
UIInput,它为我们处理了绝大繁多的底细。接下来一样的,设定自订Tag:
TextWithCmdTag.java

package onlyfun.caterpillar;

import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentTag;

public class TextWithCmdTag extends UIComponentTag {
private String size;
private String value;

public String getComponentType() {
return "onlyfun.caterpillar.TextWithCmd";
}

public String getRendererType() {
return "onlyfun.caterpillar.TextCmd";
}
}

 

要选拔自订的Component,记得要在faces-config.xml中再投入:

<component>
<component-type>
onlyfun.caterpillar.TextWithCmd
</component-type>
<component-class>
onlyfun.caterpillar.UITextWithCmd
</component-class>
</component>

<application>
    <resource-bundle>
        <base-name>com.itzhai.user</base-name>
        <var>userInfo</var>
    </resource-bundle>
</application>

然后在com.itzhai目录下开创一个国际化财富文件的basename为user:

username="arthinking"
message=用户名:{0}

3.7、panelGrid和panelGroup的使用:

<h1>panelGrid标签的使用</h1>
    <h:panelGrid columns="3" width="300px" border="1">
        <!-- 生成表格标题 -->
        <f:facet name="caption">
            <h:outputText value="表格标题" />
        </f:facet>
        <!-- 生成表格头 -->
        <f:facet name="header">
            <h:outputText value="表格头" />
        </f:facet>
        <h:outputText value="1" />
        <h:outputText value="2" />
        <h:outputText value="3" />
        <!-- panelGroup的使用 -->
        <h:panelGroup layout="block" style="color:#cfcfff">
            <h:outputText value="4" />
            <h:outputText value="5" />
        </h:panelGroup>
        <h:outputText value="6" />
        <h:outputText value="7" />
    </h:panelGrid>

panelGrid用于转移表格,panelGroup用于把多个因素结合二个要素。

三.八、使用UIData迭代输出从数额源中获取的数目:

<h1>dataTable的使用</h1>
<h:dataTable width="600px" border="1" value="showbook.bookList" var="book" rowClasses="odd,even">

    <!-- 使用facet生成caption -->
    <f:facet name="caption">
        <h:outputText value="book list" />
    </f:facet>

    <!-- 定义第一列 -->
    <h:column>
        <f:facet name="header">
            <h:outputText>图书名</h:outputText>
        </f:facet>
        <h:inputText value="#{book.name }" size="3" />
    </h:column>
    <!-- 定义第二列 -->
    <h:column>
        <f:facet name="header">
            <h:outputText>图书分类</h:outputText>
        </f:facet>
        <h:outputLink value="#{book.url }">
            <h:inputText value="#{book.bookClass }" />
        </h:outputLink>
    </h:column>

    <!-- 生成表格底部 -->
    <f:facet name="footer">
        <h:panelGroup>
            <h:outputText value="计算机书籍" />
        </h:panelGroup>
    </f:facet>
</h:dataTable>

下边需求在名称叫showbook的托管Bean中提供三个bookList数据源,能够在他的get方法中提供数据:

public List<BookInfo> getBookList(){
    List<BookInfo> books = new ArrayList<BookInfo>();
    books.add(new BookInfo("Core Java", "Java", "www.itzhai.com"));
    books.add(new BookInfo("Core Java", "Java", "www.itzhai.com"));
    books.add(new BookInfo("Core Java", "Java", "www.itzhai.com"));
    return books;
}

其中的BookInfo类如下:

public class BookInfo {

    private String name;
    private String url;
    private String bookClass;

    public BookInfo(String name, String bookClass, String url){
        this.name = name;
        this.bookClass = bookClass;
        this.url = url;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getBookClass() {
        return bookClass;
    }
    public void setBookClass(String bookClass) {
        this.bookClass = bookClass;
    }
}

3.九、图像组件的施用:

<h:graphicImage value="images/01.jpg" alt="图像01" />

其一标签将生成HTML的img标签。