JSF应用程序配置
JSF允许编程人员仅仅通过应用程序配置文件就可以轻松配置应用程序。该文件如果存在的话,则它应该被命名为faces-config.xml,并且应该位于你应用程序下的WEB-INF 目录。
可以在faces-config.xmlz文件中对该应用程序的多个方面进行配置,包括bean管理、页面导航、定制UI(用户界面)组件、定制验证程序和消息资源。在 PizzaRia 应用程序中,我将该faces-config.xml用于bean管理和页面导航的配置。
JavaBean管理。对于JavaBean管理,可以使用应用程序配置文件faces-config.xml中的managed-bean元件。每个managed-bean元件都会注册一个JavaBean--JSF会将该JavaBean在特定的作用域内实例化和进行储存。managed-bean元件定义如下:
<!ELEMENT managed-bean (description*, display-name*, icon*, managed-bean name, managed-bean-class, managed-bean-scope, (managed-property* | map-entries | list-entries))>
每个managed-bean元件都必须包含一个 managed-bean-name元件,一个managed-bean-class元件,以及一个managed-bean-scope元件,并且可选择性地包含一些描述、显示名、图标和managed-property/map-entries/list-entries元件。
managed -bean-name指定了被用来在整个应用程序中引用该JavaBean的名称。managed-bean-class元件包含该JavaBean的完全限度的类名。managed-bean-scope元件定义该JavaBean的作用域。该元件可能的值是:application、session、 request或者none。如果managed-bean-scope元件是none以外的其他值,那么,所创建的该JavaBean元件将会被存储在相应的对象中。比如说,如果值是"session",那么,该JavaBean就会被存储在一个给定用户的session对象中。
在PizzaRia应用程序中,我注册了如代码清单1所示的4个JavaBeans。
页面导航:页面导航决定了Web应用程序的控制流。本节演示如何在JSF中创立一个页面导航。
JSF使用navigation-rule元件来为页面导航定义规则。其定义如下:
<!ELEMENT navigation-rule (description*, display-name*, icon*, from-view-id?, navigation-case*)>
from-view-id元件是首页(起始页)的标识符。为了说明被称之为index.jsp的JSP页面的导航规则,下面给出子元件from-view-id的值:
<from-view-id>/index.jsp</from-view-id>
navigation-case元件表示一个可能的目标页面。navigation-rule一个元件可以有零个或者数个navigation-case子元件。
每个navigation-case元件都指定from-view-id的特定处理结果的目标页面。结果可以来自from-view-id元件中 UICommand组件的行动(action)属性。
navigation-case元件由如下所示的代码描述:
<!ELEMENT navigation-case (description*, display-name*, icon*, from-action?, from-outcome?, to-view-id, redirect?)>
to-view-id元件指定目标页面。from-outcome值是处理from-view-id的结果。该值来自于在from-view-id中触发了ActionEvent的 UICommand组件的行动属性。
from-action元件也表示处理from-view-id的结果。但其值来自于引发了ActionEvent的UICommand组件的行动属性的运算值。
代码清单2展示了在PizzaRia应用程序中使用的navigation-rule元件。
在JSP页面中使用UI组件
JSF 提供两个定制标记库来帮助用户快速编写Web应用程序:HTML和Core。HTML定制标记库定义了用来表示UI组件的标记。Core定制标记库使用具有组件的验证器(validators)定义了注册事件处理器的核心行动,以及其他一些行动。你可以在自己的JSF应用程序的JSP页面中使用这两个库的标记。
为了在JSP页面中使用HTML和Core定制标记库,必须在页面中包含如下所示的taglib指令:
<%@ taglib uri="http://java.sun.com /jsf/html/" prefix="h" %> <%@ taglib uri="http://java.sun.com/ jsf/core/" prefix="f" %>
Prefix的属性值可以是任意值。但是,根据惯例,最好是使用"h"和"f"。
在JSF应用程序中编写JSP页面是每一个页面制作者的责任。除了布置组件之外,他们的责任还包括把组件绑定到模型对象数据并且把Core标记(诸如事件监听器和验证器)添加到组件标记中。
在HTML定制标记库中有25个标记。每个组件都呈现为一个HTML元件,而多个标记被呈现为同一个HTML元件。表1列出了HTML定制标记库中的标记。
标记 | 说明 |
Column | 在UIData组件内表示一个数据列。 |
command_button | 表示一个向服务器提交表单的按钮。 |
command_link | 表示一个指向另一页面或者本页面内其他位置的超链接。 |
data_table | 表示一个支持将数据绑定到一个数据对象的集合上的表。 |
Form | 表示一个表单。 |
graphic_image | 显示一张图片。 |
input_hidden | 表示一个隐藏的元件。 |
input_secret | 表示一个密码输入框。 |
input_text | 表示一个可接受单个字符串的文本输入框。 |
input_textarea | 表示一个可接受多个字符串的文本输入区。 |
Message | 显示给定组件的信息。 |
Messages | 表示一个从FacesContext中获取消息并且将其显示给用户的组件。 |
output_label | 显示文本。 |
output_link | 显示一个超链接。 |
output_message | 显示给定组件的信息。 |
output_text | 显示一行文本。 |
panel_grid | 显示一张表。 |
panel_group | 将一个组件集合分组。 |
selectboolean_checkbox | 表示一个单选文本框。 |
selectmany_checkboxlist | 显示一套复选框,用户从中可以选择多个值。 |
selectmany_listbox | 表示一个多选下拉选择框,用户从中可以选择多个项目。 |
selectmany_menu | 表示一个多选项目列表,用户从中可以选择多个项目。 |
selectone_listbox | 表示一个单选下拉选择框,用户从中只能选择一个项目。 |
selectone_menu | 表示单选项目列表,用户从中只能选择一个项目。 |
selectone_radio | 表示一套单选按钮。 |
使用验证器
验证器使得输入确认简单化并且可以节省开发人员的大量编程时间。JSF提供一套验证器类用于确认输入到输入组件中的值。另外一种方法就是,如果现有的标准验证器不符合需要,那么开发人员还可以编写自己的验证器。
验证器是一个实现类(implementation class),它可以验证输入值,如果是非法输入,就会发出一个错误信息。可以通过将一个验证器嵌入一个其输入需要验证的输入组件中来使用它。如果该验证器判断出用户的输入是非法的,那么JSF servlet就会重新显示刚才提交了表单的那个JSP页面,而不会将本地值复制给绑定到该输入组件上的JavaBean实例。
JSF实现为通用的验证任务提供了3个标准验证器,包括检查必填的域内已填入内容、输入的内容符合长度和范围要求。表2列举了标准的验证器。
验证器类 | 标记 | 说明 |
LengthValidator | validate_length | 确保组件的本地值的长度在规定的范围之内。该值必须是字符串型。 |
LongRangeValidator | validate_longrange | 确保组件的本地值在规定的范围之内。该值必须能够被转换成长型。 |
DoubleRangeValidator | validate_doublerange | 确保组件的本地值在规定的范围内。该值必须能够被转换成浮点型。 |
另外,HTML定制标记库中的input_text和input_textarea标记有必填的属性。如果将该属性标赋值为真,那么用户在继续进行操作之前,就必须对文本输入框元件或者文本输入区域进行填写。
在PizzaRia应用程序中,checkOut.jsp页面使用该必填的属性以便保证没有一个域是空的。
事件处理
JSP应用程序是事件驱动型的程序。在JSF中处理事件令人惊奇的简单。以下是处理步骤:
- 编写事件监听器。
- 在程序目录下的WEB-INF/classes or WEB-INF/lib目录中部署事件监听器。
- 在表示组件(其事件被捕获)的标记中,使用Core定制标记库中定义的action_listener或者 valuechange_listener标记。
在JSF中的事件对象。JSF中的所有事件对象必须提供javax.faces .event.FacesEvent类,以便这些事件被请求处理生命周期支持。FacesEvent类是java.util.EventObject的子类,并添加了getComponent方法,该方法返回引发该事件的UIComponent组件。
FacesEvent类有两个子类:ActionEvent和 ValueChangeEvent。ActionEvent类激活诸如UICommand组件之类的UI组件。
ValueChangeEvent类会发出一个通知,告知本地UIInput组件的值被修改了。然而,如果新值没有被成功地验证为合法的,则不会发出ValueChangeEvent通知。被加入到该类中的两个重要方法是getOldValue 和 getNewValue。getOldValue方法返回引发该事件的组件的旧值。getNewValue方法返回相应的新值。这两种方法的返回值类型都是java .lang.Object。
第三,JSF中的事件监听器。
为捕获一个JSF事件,需要使用一个事件监听器。JSF程序中的所有监听器都必须实现javax.faces.event.FacesListener接口。该接口提供java.util.EventListener接口,后者是必须由所有Java事件监听器实现的接口。
Faces Listener接口有两个子接口:ActionListener 和 ValueChangeListener。ActionListener接口是为了捕获ActionEvent而必须被实现的接口。该接口添加了一个新的方法--processAction--该方法请求处理生命周期来调用。当为之注册了ActionListener 的ActionEvent发生事件时,就会调用processAction。processAction方法的代码如下:
public void processAction(ActionEvent event) throws AbortProcessingException
ValueChangeListener接口是为了捕获ValueChangeEvent而实现的接口。该接口添加了一个方法: processValueChange。当ValueChangeEvent动作被其监听者监听到时,就会调用processValueChange方法。processValueChange方法的代码如下:
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException
阅读 |
AppActionListener类使用两个非常有用的方法:getValueBinding 和getDatabaseUtil。getValueBinding接受指定对象名的字符串,并返回一个可以向下转换类型为对象类型的ValueBinding对象。比如说,为获得用户的在应用程序配置文件中被注册成shoppingCartBean 的ShoppingCartBean实例,开发人员需要通过传递"shoppingCartBean"来调用getValueBinding。
ShoppingCartBean cart = (ShoppingCartBean) getValueBinding("#{shoppingCartBean}").getValue(facesContext);
getValueBinding方法如下:
private ValueBinding getValueBinding(String valueRef) { ApplicationFactory factory = (ApplicationFactory)FactoryFinder .getFactory(FactoryFinder .APPLICATION_FACTORY); Application application = factory.getApplication(); return application.createValueBinding (valueRef); }
getDatabaseUtil方法返回一个对ServletContext中的DatabaseUtil实例的引用:
private DatabaseUtil getDatabaseUtil() { FacesContext facesContext = FacesContext.getCurrentInstance(); ServletContext servletContext = (ServletContext) facesContext.getExternalContext() .getContext(); return (DatabaseUtil) servletContext .getAttribute("DATABASE_UTIL"); }摘自: http://www.oracle.com/global/cn/oramag/oracle/04-mar/o24dev_jsf.html