本文最后一次修改时间:2012-05-02。
开发环境 :JDeveloper 11.1.2.1.0。
我们知道JSF把一个页面分为了六个阶段,组件上的不同的事件发生在不同的阶段。
组件上的有些属性可能会改变事件发生的阶段。
为了能够清楚地了解这些事件发生的阶段,我们需要使用PhaseListener来观察JSF生命周期。
1. PhaseListener 代码如下:
package com.javaneverdie.adf.lifecycle.view.phaselistener;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
public class MyPhaseListener implements PhaseListener {
public MyPhaseListener() {
super();
}
public void beforePhase(PhaseEvent pe) {
if (pe.getPhaseId() == PhaseId.RESTORE_VIEW)
System.out.println("###### Processing new Request!");
System.out.println("before - " + pe.getPhaseId().toString());
}
public void afterPhase(PhaseEvent pe) {
System.out.println("after - " + pe.getPhaseId().toString());
if (pe.getPhaseId() == PhaseId.RENDER_RESPONSE)
System.out.println("###### Done with Request!\n");
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}
2. BackingBean 代码如下:
package com.javaneverdie.adf.lifecycle.view.backing;
public class MyBackingBean {
public MyBackingBean() {
super();
}
public String clickMe_action() {
System.out.println("$$$$$ Action event processed...");
return "success";
}
}
3. Validator 代码如下:
package com.javaneverdie.adf.lifecycle.view.validator;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
public class MyValidator implements Validator {
public MyValidator() {
super();
}
public void validate(FacesContext context, UIComponent component,
Object obj) throws ValidatorException {
System.out.println("$$$$$ Validate processed...");
}
}
4. ValueChangeListener 代码如下:
package com.javaneverdie.adf.lifecycle.view.valuechangelistener;
import javax.faces.event.ValueChangeListener;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.AbortProcessingException;
public class MyValueChangeListener implements ValueChangeListener {
public MyValueChangeListener() {
}
public void processValueChange(ValueChangeEvent vce) throws AbortProcessingException {
System.out.println("$$$$$ Value Change event processed...");
}
}
5. faces-config.xml 内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee">
<application>
<default-render-kit-id>oracle.adf.rich</default-render-kit-id>
</application>
<lifecycle>
<phase-listener>com.javaneverdie.adf.lifecycle.view.phaselistener.MyPhaseListener</phase-listener>
</lifecycle>
<managed-bean>
<managed-bean-name>myBackingBean</managed-bean-name>
<managed-bean-class>com.javaneverdie.adf.lifecycle.view.backing.MyBackingBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<validator>
<validator-id>myValidator</validator-id>
<validator-class>com.javaneverdie.adf.lifecycle.view.validator.MyValidator</validator-class>
</validator>
</faces-config>
好,下面我们就可以做一些有意思的实验了。
实验1:页面中只有一个Button,代码如下:
<h:commandButton value="Click Me" id="cb1" action="#{myBackingBean.clickMe_action}"/>
第一次Run的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
我们注意到,页面初始化时,只进入了两个生命周期阶段:RESTORE_VIEW 1 和 RENDER_RESPONSE 6。
这符合JSF生命周期的规范,详细说明请参考《JSF 的生命周期》。
点击按钮后的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - APPLY_REQUEST_VALUES 2
after - APPLY_REQUEST_VALUES 2
before - PROCESS_VALIDATIONS 3
after - PROCESS_VALIDATIONS 3
before - UPDATE_MODEL_VALUES 4
after - UPDATE_MODEL_VALUES 4
before - INVOKE_APPLICATION 5
$$$$$ Action event processed...
after - INVOKE_APPLICATION 5
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
我们注意到,因为点击了按钮,相当于发出了POST请求,页面经历了完整的六个阶段。其中按钮上的action事件是在INVOKE_APPLICATION 5阶段被调用。
实验2:页面代码同上,只是增加immediate="true":
点击按钮后的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - APPLY_REQUEST_VALUES 2
$$$$$ Action event processed...
after - APPLY_REQUEST_VALUES 2
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
点击了按钮,相当于发出了POST请求,本来页面应该经历完整的六个阶段。
但是,因为按钮上的immediate="true",我们发现只经历了三个阶段,并且按钮上的action事件是在APPLY_REQUEST_VALUES 2阶段被调用。
实验3:一个InputText,一个validator,一个valueChangeListener,一个Button,页面代码如下:
<h:inputText value="hello">
<f:valueChangeListener type="com.javaneverdie.adf.lifecycle.view.valuechangelistener.MyValueChangeListener"/>
<f:validator validatorId="myValidator"/>
</h:inputText>
<h:commandButton value="Submit" id="cb1" action="#{myBackingBean.clickMe_action}"/>
点击按钮后的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - APPLY_REQUEST_VALUES 2
after - APPLY_REQUEST_VALUES 2
before - PROCESS_VALIDATIONS 3
$$$$$ Validate processed...
$$$$$ Value Change event processed...
after - PROCESS_VALIDATIONS 3
before - UPDATE_MODEL_VALUES 4
after - UPDATE_MODEL_VALUES 4
before - INVOKE_APPLICATION 5
$$$$$ Action event processed...
after - INVOKE_APPLICATION 5
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
点击了按钮,相当于发出了POST请求,页面经历了完整的六个阶段。
其中值得注意的是,validator先调,valueChangeListener后调,两个事件都在PROCESS_VALIDATIONS 3阶段中被调用。
这其实符合我们一般的认识:只有验证通过了,才应该产生值变事件。
实验4:页面代码同上,只是在按钮上增加immediate="true":
点击按钮后的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - APPLY_REQUEST_VALUES 2
$$$$$ Action event processed...
after - APPLY_REQUEST_VALUES 2
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
点击了按钮,相当于发出了POST请求,本来页面应该经历完整的六个阶段。
但是,因为按钮上的immediate="true",我们发现只经历了三个阶段。
其中值得注意的是,InputText上的validator和valueChangeListener并没有被调用!
这其实是我们在命令组件上使用immediate="true"的最常用的一个原因:跳过验证,直接处理action事件。
另外我们注意到,按钮上的action事件是在APPLY_REQUEST_VALUES 2阶段被调用得。
实验5:如果在输入组件上设置immediate="true",会有怎样的效果呢?代码如下:
<af:form id="f1">
<h:inputText value="hello" immediate="true">
<f:valueChangeListener type="com.javaneverdie.adf.lifecycle.view.valuechangelistener.MyValueChangeListener"/>
<f:validator validatorId="myValidator"/>
</h:inputText>
<h:inputText value="hello2">
<f:valueChangeListener type="com.javaneverdie.adf.lifecycle.view.valuechangelistener.MyValueChangeListener2"/>
<f:validator validatorId="myValidator2"/>
</h:inputText>
<h:commandButton value="Submit" id="cb1" action="#{myBackingBean.clickMe_action}"/>
</af:form>
点击按钮后的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - APPLY_REQUEST_VALUES 2
$$$$$ Validate processed...
$$$$$ Value Change event processed...
after - APPLY_REQUEST_VALUES 2
before - PROCESS_VALIDATIONS 3
$$$$$ Validate 2 processed...
$$$$$ Value Change 2 event processed...
after - PROCESS_VALIDATIONS 3
before - UPDATE_MODEL_VALUES 4
after - UPDATE_MODEL_VALUES 4
before - INVOKE_APPLICATION 5
$$$$$ Action event processed...
after - INVOKE_APPLICATION 5
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
我们注意到第1个InputText的validator和valueChanger发生在APPLY_REQUEST_VALUES 2阶段,这是因为在这个InputText上的immediate="true"。
而第2个InputText的validator和valueChanger发生在PROCESS_VALIDATIONS 3阶段。
实验6:如果在第1个InputText上验证错误了以后,是否还会验证第2个InputText呢?
我们让第1个InputText上的validator抛出异常 throw new ValidatorException(message);
点击按钮后的结果:
###### Processing new Request!
before - RESTORE_VIEW 1
after - RESTORE_VIEW 1
before - APPLY_REQUEST_VALUES 2
$$$$$ Validate processed...
after - APPLY_REQUEST_VALUES 2
before - RENDER_RESPONSE 6
after - RENDER_RESPONSE 6
###### Done with Request!
从结果可以看出,由于第1个InputText验证没有通过,因此第2个InputText的validator也不再被调用了。
也就是说,在没有改正第1个InputText的错误之前,其它的验证器都不会起作用。
Project 下载:JSF_Lifecycle.7z
没有评论:
发表评论