浏览 3990 次
锁定老帖子 主题:jsf-四种事件
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-04-15
下面将一一说明: 动作事件: 通过ActionListener来监听动作事件 先来看一段简单的jsf页面代码: <h:commandButton value="送出" action="#{user.verify}"/> 以上代码中虽然没有涉及ActionListener,但jsf为其默认产生了预定义的ActionListener. 实际过程是这样: JSF会先检查是否有指定的actionListener,然后再检查是否指定了动作方法并为其产生预定义的ActionListener,并根据其传回值导航页面. 动作事件三种触发方法: 方法一: 通过指定动作方法 <h:commandButton value="送出" action="#{user.verify}"/> 方法二: 通过指定ActionListener属性 <h:commandButton value="送出" actionListener="#{user.verify}" action="#{user.outcome}"/> 方法三: 通过<f: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) { // 处理验证 } } <h:commandButton value="送出" action="#{user.outcome}"> <f:actionListener type="onlyfun.caterpillar.LogHandler"/> <f:actionListener type="onlyfun.caterpillar.VerifyHandler"/> </h:commandButton> 即时事件: 所谓的即时事件(Immediate Events),是指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 Event)来说,组件的动作事件是在套用请求值阶段就生成ActionEvent对象了,但相关的事件处理并不是马上进行,ActionEvent会先被排入队列,然后必须再通过验证、更新方式值阶段,之后才处理队列中的事件。 这样的流程对于按下按钮然后执行后端的应用程序来说不成问题,但有些事件并不需要这样的流程,例如只影响页面的事件。 举个例子来说,在表单中可能有使用者名称、密码等栏目,并提供有一个地区选项按钮,使用者可以在不填写名称、密码的情况下,就按下地区选项按钮,如果依照正常的流程,则会进行验证、更新模型值、唤起应用程序等流程,但显然的,使用者名称与密码是空白的,这会引起不必要的错误。 您可以设定组件的事件在套用请求值之后立即被处理,并跳过后续的阶段,直接进行页面绘制以响应请求,对于JSF的input与command组件,都有一个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。 值变事件 如果使用者改变了JSF输入组件的值后提交表单,就会发生值变事件(Value Change Event),这会丢出一个javax.faces.event.ValueChangeEvent对象,如果您想要处理这个事件,有两种方法: 方法一 直接设定JSF输入组件的valueChangeListener属性,例如: <h:selectOneMenu value="#{user.locale}" onchange="this.form.submit();" valueChangeListener="#{user.changeLocale}"> <f:selectItem itemValue="zh_CN" itemLabel="Chinese"/> <f:selectItem itemValue="en" itemLabel="English"/> </h:selectOneMenu> 注意在此为了模拟GUI中选择了选单项目之后就立即发生反应,我们在onchange属性中使用了JavaScript,其作用是在选项项目发生改变之后,立即提交表单,而不用按下提交按钮 方法二 实现javax.faces.event.ValueChangeListener接口,并定义其processValueChange()方法,例如: • SomeListener.java package onlyfun.caterpillar; .... public class SomeListener implements ValueChangeListener { public void processValueChange(ValueChangeEvent event) { .... } .... } 然后在JSF页面上使用<f:valueChangeListener>标签,并设定其type属性,例如: <h:selectOneMenu value="#{user.locale}" onchange="this.form.submit();"> <f:valueChangeListener type="onlyfun.caterpillar.SomeListener"/> <f:selectItem itemValue="zh_CN" itemLabel="Chinese"/> <f:selectItem itemValue="en" itemLabel="English"/> </h:selectOneMenu> Phase事件 在即时事件中我们提到,JSF的请求执行到反应,完整的过程会经过六个阶段. 在每个阶段的前后会引发javax.faces.event.PhaseEvent,如果您想尝试在每个阶段的前后捕捉这个事件,以进行一些处理,则可以实现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> 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |