1.5 Hello, world! 解剖 -JSF实战 -hxzon -jsf学习笔记html
既然已经对JSF可以解决什么问题有了初步理解,咱们来开始开发一个简单的应用。本节假定你已熟悉Java Web应用和JSP(关于这些技术的信息,参考1.2节)。下面来解剖一个简单的基于HTML的Web应用,该应用有两个页面:hello.jsp 和 goodbye.jsp。java
hello.jsp页面作如下工做:web
l 显示文本“Welcome to JSF!”;浏览器
l 有一个表单,其中有个文本框,要求输入1 到 500 的整数;服务器
l 在名为numControls 的JavaBean 属性中存储提交的文本值;框架
l 文本框下面有个表格;jsp
l 有一个标签为Redisplay的按钮,点击它时,将添加一个numControls 输出UI组件到表格中(清除先前已经有了的UI组件);ide
l 有一个标签为Goodbye的按钮,点击它将显示goodbye.jsp 页面。工具
goodbye.jsp 页面作如下工做:学习
l 显示文本“Goodbye!”;
l 显示JavaBean 属性numControls的值。
JSF执行Hello, world!应用程序的大部分工做,可是除了JSP 页面以外,还有一些其余要求:
l HelloBean后台bean类;
l Faces配置文件;
l 正确配置的部署描述符。
某些工具能够简化部分或者所有需求的建立工做,但在本节,咱们将详细讨论这些原始文件。
在涉足细节以前,先看看Hello, world!在Web浏览器中怎样显示。应用以hello.jsp开始,如图1-7所示。页面中的文本框与HelloBean类中的一个JavaBean属性相关联;当用户在此文本框中输入一个值,属性将自动更新(若是值有效)。
图1-7 数据提交以前的Hello, world!应用程序
若是在文本框中输入数字64,点击Redisplay 按钮,页面将从新显示,如图1-8,共有64个UI输出组件显示在表格中。若是清除文本框,而后点击Redisplay按钮,将会获得一个验证错误,如图1-9所示。若是输入数字99999,而后点击Redisplay按钮,也会获得验证错误,如图1-10。
图1-8 输入“64”而且点击Redisplay按钮后的Hello,world!应用程序。表格内组装了64个UI输出组件
图1-9 对必须填写的字段提交空值,而且点击Redisplay按钮后的Hello,world!应用程序。由于发生了验证错误,相关JavaBean属性的值未被修改
不要担忧错误信息,你彻底能够在本身的应用中定制它们。重点在于,在这两种状况下,表单提交时,相关的 JavaBean属性未被修改。
若是点击Goodbye 按钮,你将看到goodbye.jsp页面,如图1-11。虽然这是彻底不一样的页面,JavaBean 属性的值也会显示。JSF组件能够引用应用做用域中的JavaBean。
Hello, world! 示例是一个标准的Java Web应用,它使用标准的Servlet API(虽然它要求标准的Faces 库)。这五个图都是由两个JSP产生的。接下来详细讨论一下。
1.5.1 解剖hello.jsp
主页面hello.jsp提供了图1-7~图1-10的界面。JSF 经过使用定制标签库与JSP集成。JSF 定制标签容许JSP使用Faces UI组件。某些工具使你能够经过从面板拖放JSF组件来设计JSP页面。事实上,图1-1~图1-3就是在不一样的IDE中设计hello.jsp 的屏幕截图。这些IDE最终都产生与代码清单1-1相似的代码(固然,也能够手工编写JSF页面)。
图1-10 在文本框内输入"99999",而后点击Redisplay后的Hello, world!应用程序。字段仅接受1~500之间的数值,因此产生如图所示的验证错误。由于发生了验证错误,相关的JavaBean属性的值未被修改
图1-11 点击Goodbye按钮后的Hello, world!应用程序。注意JavaBean 属性,它与第一个页面中的文本字段保持同步,也显示在此页面中
代码清单1-1 hello.jsp: Hello,world! 应用程序的起始页面(浏览器输出如图1-7~图1-10所示)
首先,导入核心JSF标签库。该库提供诸如验证和事件处理之类的基本任务的定制标签。接着,导入基本HTML标签库,它提供诸如文本框、输出标签和表单之类的UI组件(前缀f和h是建议的,非必要)。
<f:view>标签必须将全部其余Faces相关的标签包围起来(包括来自于核心标签和基本HTML标签库中的标签)。
<h:form>标签表示HtmlForm组件,它是其余组件的容器,并将信息提交给服务器。在一个页面内能够有多个HtmlForm,但输入组件必须嵌入<h:form>标签中。
<h:outputText>标签建立HtmlOutputText 组件,该组件只是在屏幕上显示只读数据。此标签有一个id属性和一个value 属性。id 属性对每一个组件是可选的,不是必需属性,除非你想要在其余地方引用该组件(组件可使用客户端技术(如JavaScript)引用或者在Java 代码中引用)。Value属性的值是须要显示的文本。
<h:message>标签表示HtmlMessage 组件,它显示特定组件的验证和转换错误信息。for 属性告诉它须要显示针对标识符为helloInput的组件的错误信息。helloInput是页面中
处的文本框的标识符。若是没有错误则什么都不显示。
<h:outputLabel>标签建立新的HtmlOutputLabel组件,它用做输入控件的标注。for属性将它与该输入控件相联系,即 helloInput 文本框
。HtmlOutputLabel不显示内容,因此还须要下属HtmlOutputText(由嵌套的<h:outputText> 标签建立)来显示标注的文本。
<h:inputText>标签用于建立HtmlInputText 组件,该组件接收用户的文本输入。注意,该组件的value 属性是"#{helloBean.numControls}",这是JSF表达式语言(EL)写成的表达式,引用了后台bean中的numControls 属性,该bean名为HelloBean(JSF EL 基于JSP 2.0引入的表达式语言)。
Faces将自动在不一样的上下文(请求、会话、应用)中查询特定的后台bean。这样,它将在应用会话中找到在关键字helloBean下保存的后台bean。组件的value属性和helloBean的numControls 属性是同步的,其中一个变化了,另外一个也要修改(除非HtmlInputText 组件中的文本无效)。
输入组件有个required 属性,它决定该字段是否必须有一个值。这样,若是required 属性被设置为true,则组件只能接受非空输入。若是用户输入空值,页面将从新显示,而HtmlMessage()将显示错误信息,如图1-9所示。
JSF也支持验证器,它负责确保用户的输入是可接受的值。每一个输入控件均可以与一个或者多个验证器相关联。<f:validateLongRange>标签注册LongRange验证器到HtmlInputText 组件。验证器检查输入值以确保用户输入是在预设的0~500之间的一个数(包含端点)。若是用户输入一个超出此范围的值,验证器将拒绝该输入,页面从新显示,而且HtmlMessage()组件显示错误信息,如图1-10所示。
当用户输入被拒绝时,HtmlInputText组件引用的对象的value 属性不会更新。
HtmlPanelGrid 组件用<h:panelGrid> 标签来表示。HtmlPanelGrid表现为其余组件的可配置容器,将显示为HTML表格。
许多JSF 组件均可以经过其JSP标签的binding属性直接与后台bean相联系(某些工具可以自动使页面上的全部组件与后台bean相联系)。此标签的binding属性被设置为"#{helloBean.controlPanel}"。这也是JSF EL表达式,它引用了helloBean的controlPanel属性,这是HtmlPanelGrid类型的属性。这样确保helloBean 老是可以访问页面上的HtmlPanelGrid 组件。
<h:commandButton>表示HtmlCommandButton 组件,它显示为HTML表单按钮。HtmlCommandButton在被用户点击后会发送动做事件(Action Event)到服务器中的应用。可经过actionListener属性直接引用事件监听器(执行事件响应的方法)。第一个HtmlCommandButton的actionListener属性设置为"#{helloBean.addControls}"。这还是JSF EL表达式,它告诉JSF去查找helloBean 对象,而后调用其addControls 方法来处理事件。一旦方法执行完毕,页面将从新显示。
第2个HtmlCommandButton按钮设置action属性而不是actionListener属性。该属性的值为"#{helloBean.goodbye}",这个表达式引用一个特定的处理导航的事件监听器。这也是为何点击这个按钮将显示goodbye.jsp页面,而不是从新显示hello.jsp页面的缘由。这个按钮还有个immediate 属性设置为true,这告诉JSF在验证和更新发生前就执行相关的监听器。这样,即便输入不正确,点击此按钮也能够工做。这就是整个hello.jsp。
代码清单1-2列出了验证出错后的HTML输出(浏览器的视图显示效果示于图1-10)。
代码清单1-2 hello.jsp的HTML输出(此代码是图1-10的源代码)
你能够看到,在JSP中定义的每个组件都在HTML页面中有一个对应的显示。注意,<h:form>标签(),它表示HtmlForm组件,有一个action属性,它指向调用此页面的JSP,可是有一个前缀faces。这是Faces servlet的一个别名,是在应用的部署描述符中定义的。从新显示调用页面是默认行为,但Faces应用也能够导航到其余页面(这发生在用户点击Goodbye按钮后)。
HtmlMessage组件()的输出是文本“Validation Error: Specified attribute is not between the expected values of 1 and 500。”正如你所想,此消息是由注册到页面中的LongRange 验证器产生的。当验证器拒绝提交输入不正确值的尝试时,它也产生错误信息,而框架则避免更新相关的JavaBean的属性值。
对应于JSF组件的每一个HTML元素都有个继承自JSP中指定的id值的id属性(若是没有指定,将自动建立一个)。这就是客户端标识符(client identifier),它是JSF用来将输入值映射到服务器组件的标识。某些组件也使用name属性做为客户端标识符。
HtmlPanelGrid组件()的输出是HTML表格。注意,JSP中的border 和cellspacing 属性直接传递到HTML(大多数标准HTML组件都会暴露一些直接传递到浏览器的HTML特定属性)。表格中的每一个单元格都输出一个HtmlOutputText组件,它是经过Java代码在响应用户点击Redisplay按钮后添加到其中的(在实际的HTML中,有64 个单元格,由于这是用户在文本框中输入的数字。咱们省略了部分代码,不然将会浪费大量的篇幅!)。
咱们很快就会研究Java代码,但如今先来看看goodbye.jsp。
1.5.2 解剖goodbye.jsp
goodbye.jsp页面的效果如图1-11所示,用户点击Goodbye按钮后显示。页面代码(代码清单1-3)包含了一些与hello.jsp 页面中的组件相同的组件:导入JSF标签库、一个HtmlForm组件、HtmlOutputText组件。其中一个HtmlOutputText组件引用与前一个页面中相同的helloBean 对象。这运行得很好,由于对象在应用的会话中,能够在页面请求间存活。
代码清单1-3 goodbye.jsp: Hello, world!应用程序的结束页面(浏览器输出示于图1-11)
此页面产生的HTML和前一节相比无特别须要说明之处,所以就再也不浪费时间。重要的是能够建立有功能的应用了,包括验证和导航,尽管仅有两个页面(若是不打算展现导航,第一个页面就已足够了)。
如今,咱们来看页面背后的代码。
1.5.3 检视HelloBean类
hello.jsp和goodbye.jsp都包含了经过JSF EL表达式引用名为helloBean的后台bean的JSF组件。这个JavaBean包含了此应用所需的全部内容:两个属性和两个方法。其代码如代码清单1-4所示。
代码清单1-4 HelloBean.java: Hello, world!应用程序的简单后台bean
|
与其余不少框架不一样,JSF后台bean并非非要继承自特定的类。它们只须要简单地遵循普通的JavaBean约定,在事件处理方法中使用特定的方法签名暴露其属性便可。
numControls属性被hello.jsp的HtmlInputText组件和goodbye.jsp中的HtmlOutputText组件所引用。不管什么时候用户改变 HtmlInputText 组件的值,此属性的值都要相应改变(若是输入有效)。
controlPanel属性的类型是HtmlPanelGrid,后者是在hello.jsp中使用<h:panelGrid>标签建立的实际的Java类。该标签的binding属性与由controlPanel属性的标签建立的组件相关。这样使HelloBean可以操做实际的代码,即在
处执行的任务。
addControls是用来处理action 事件的方法(即动做监听器方法);你能辨别,由于它接受ActionEvent做为其惟一的参数。在hello.jsp中,Redisplay按钮HtmlCommandButton经过其actionListener属性引用这个方法。这就告诉JSF,在处理用户点击Redisplay按钮时产生的动做事件时,调用这个方法(若是你习惯使用Swing之类的框架,将组件和事件监听器相联系会显得有些奇怪,由于它们一般须要一个单独的事件监听器接口。JSF也支持接口风格的监听器,可是最好的方法仍是使用监听器方法,由于它缓解了后台bean中对适配器类的需求)。
此方法被执行时,它添加新的HtmlOutputText组件到controlPanel中,并执行numControls次(首先清零)。因此,若是numControls的值是64,如例中所述,代码将建立并添加64个HtmlOutputText实例到controlPanel中。每一个实例的值被设置为其顺序号,从0开始直到63。最后,每一个实例的style属性都设置为"color: blue"。
controlPanel是HtmlPanelGrid 实例,它将在HTML表格中显示其全部的子控件,每一个HtmlOutputText 组件将在一个单独的表格单元中显示。图1-8显示方法执行后controlPanel的样子。
与addControls方法相似,goodbye方法也是事件监听器。然而,它与JSF的导航系统相关联,因此其职责是返回一个字符串,或者是一个逻辑结果,因而导航系统使用这个结果来决定下一步将载入哪一个页面。这种类型的方法称为动做方法(action method)。hxzon:方法无参数,返回一个字符串,决定导航,对应action属性。而以前addControls带有一个ActionEvent参数,无返回值,处理事件。对应actionListener属性。
goodbye方法经过hello.jsp中的“Goodbye”按钮HtmlCommandButton的action属性与该按钮相关联。因此用户点击Goodbye按钮时,goodbye方法被执行。在这里,goodbye 并不执行决定逻辑结果的工做,它只是直接返回"success"。这一结果在Faces 配置文件中与特定的页面相关联,咱们将在下面说起。
由于goodbye方法不执行任何处理( 在实际应用中也可能如此),咱们能够在按钮的action属性中经过硬编码"success"来达到一样的效果。这是由于导航系统可使用HtmlCommandButton的action属性,也可使用action 方法的结果(若是该属性引用了动做方法)。
1.5.4 经过faces-config.xml进行配置
相似于大部分框架,Faces 也有一个配置文件;它名为faces-config.xml(技术上说,JSF支持多个配置文件,可是如今先保持简化)。这一配置文件容许你定义导航规则、初始化JavaBean、注册本身的JSF组件和验证器(validator)以及配置JSF应用的其余部分。这里的简单应用只需配置bean初始化和导航。具体的配置文件如代码清单1-5所示。
代码清单1-5 faces-config.xml : Hello world! 应用程序的Faces配置
首先,JSF配置文件是XML文档,根节点是<faces-config>()。
在此文件中,能够声明一个或者多个在应用中使用的JavaBean。能够给它们分别设置一个名字(该名称可经过JSF EL表达式引用)、一个说明、一个范围,甚至能够初始化它们的属性。在配置文件中声明的对象称为受管bean(managed bean)。在代码清单中,咱们声明了在整个Hello, world!应用程序中使用的helloBean对象()。请注意,对象的名称是"helloBean",这与在两个JSP中的JSF EL表达式中使用的名称是同样的。其实现类是org.jia.hello.HelloBean,这是在前一节所讲的后台bean类的名称。受管bean 的名称和对象的类名称不必定相同。
声明导航和声明受管bean同样简单。每一个JSF 应用能够有一个或者多个导航规则。一个导航规则定义了从特定页面出发的可能路由。每种路由称为一个导航案例(navigation case)。配置文件清单显示了Hello, world!应用程序的hello.jsp页面的导航规则()。hello.jsp有个Goodbye 按钮,该按钮用于载入另外一个页面,因此这里只有一个单一导航案例:若是结果是"success",则显示goodbye.jsp。这个结果是由helloBean的 goodbye 方法返回的,该方法在用户单击Goodbye按钮时被执行。
值得指出的是JSF 配置的某些方面,特别是导航,可使用工具进行可视化处理。如今,来看看应用程序在Web应用的层面是如何配置的。
1.5.5 配置web.xml
全部的J2EE Web应用都经过web.xml 部署描述符来进行配置,Faces应用也不例外。然而,JSF 应用要求你必须指定FacesServlet,而这一般是应用的主servlet。另外,请求必须被映射到这个servlet。咱们的Hello, world!应用程序的部署描述符如代码清单1-6所示。你可使用一些工具来产生Faces应用所须要的元素。
代码清单1-6 web.xml:Hello world!应用程序的部署描述符
到此,咱们剖析完了Hello world!。你能够看到,JSF作了大部分的工做——验证、事件处理、导航及UI组件管理等等。随着更加深刻地探讨JSF的各个方面,你将得到对其所提供的各类服务的更深的理解,从而能够将它应用在你的应用程序中,而避免一些使人抱怨的繁琐工做。
hxzon:faces-config.xml中,配置托管bean,导航规则。托管bean既是model也是action。
导航规则from-view-id表示触发的页面,from-outcome表示前进页面的逻辑名(由导航方法返回),to-view-id表示前进的页面位置。一个managed-bean配置一个托管bean,一个navigation-rule配置一个页面的导航规则(前进规则)。
http://hi.baidu.com/hxzon/blog/item/498cc9fc33ee878ab801a0c8.html