1.JSF动作事件
前面的例子,我们直接将按钮的action绑定到一个Bean的方法上。实际上当按钮被触发时,JSF会自动产生一个Listener来处理事件。
如果您需要使用同一个方法来应付多种事件来源,并想要取得事件来源的相关讯息,您可以让处理事件的方法接收一个javax.faces.event.ActionEvent事件参数。
如下jsp:
<%@ taglib
uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib
uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ page
language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>Insert title
here</title>
</head>
<body>
<f:view>
<f:form>
<h3>JSF动作事件--按钮触发的Listener事件,会在后台打出log。</h3>
<h:commandButton value="#{msgs.commandText}">
<f:actionListener
type="test.LogHandler"/>
</h:commandButton>
</f:form>
</f:view>
</body>
</html>
生成一个自定义的Listener:
package
test;
import
javax.faces.event.ActionEvent;
import
javax.faces.event.ActionListener;
public
class LogHandler implements ActionListener{
public void processAction(ActionEvent e)
{
System.out.println("++++++++LogHandler+++++++++");
}
}
当按钮触发时,便会激活LogHandler这个Listener。你也可以同时指定多个Listener。
http://localhost:8080/jsfTest/pages/jsfMyActionEvent.faces
就可以看到运行结果了。
具体程序参看示例程序。
2.JSF变量/值变事件
如果使用者改变了JSF输入元件的值后送出表单,就会发生值变事件(Value
Change Event),这会丢出一个javax.faces.event.ValueChangeEvent物件。
如果您想要处理这个事件,有两种方式,一是直接 设定JSF输入元件的valueChangeListener属性:
jsfMyValueEvent.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=utf-8"%>
<f:view
locale="#{valueEventBean.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:selectOneMenu
value="#{valueEventBean.locale}"
onchange="this.form.submit();"
valueChangeListener="#{valueEventBean.changeLocale}">
<f:selectItem itemValue="zh_TW"
itemLabel="Chinese"/>
<f:selectItem itemValue="en"
itemLabel="English"/>
</h:selectOneMenu>
</h:form>
</body>
</html>
</f:view>
onchange属性中使用了JavaScript,其作用是在选项项目发生改变之后,立即送出表单,而不用按下提交按钮。
valueChangeListener属性所绑定的user.changeLocale方法必须接受ValueChangeEvent物件。
JsfMyValueEvent.java
package test;
import javax.faces.event.ValueChangeEvent;
public class JsfMyValueEvent {
private String locale = "en";
public String
changeLocale(ValueChangeEvent e) {
if(locale.equals("en"))
locale = "zh_TW";
else
locale = "en";
return locale;
}
public String getLocale() {
if (locale == null) {
locale = "en";
}
return locale;
}
}
别忘记在faces-config.xml中注册Bean。
http://localhost:8080/jsfTest/pages/jsfMyValueEvent.faces
可以查看运行结果。
具体程序见示例程序。
另一个方法是实现javax.faces.event.ValueChangeListener接口,并实现其processValueChange()方法。
在jsp中直接用标签<f:valueChangeListener 引用。见例:
…
<h:form>
<h3><h:outputText
value="#{msgs.hintText}"/></h3>
<h:selectOneMenu
value="#{valueEventBean.locale}"
onchange="this.form.submit();">
<f:valueChangeListener
type="……"/>
<f:selectItem itemValue="zh_TW"
itemLabel="Chinese"/>
<f:selectItem itemValue="en"
itemLabel="English"/>
</h:selectOneMenu>
</h:form>
…
与上面一种的写法有些区别,请注意。
这里就不再演示了。
对于动作事件(Action
Event)来说,元件的动作事件是在套用请求值阶段就生成ActionEvent物件了,
但相关的事件处理并不是马上进行,ActionEvent会先被排入伫列,然后必须再通过验证、更新模式值阶段,之后才处理伫列中的事件。
可以设定元件的事件在套用请求值之后立即被处理,并跳过后续的阶段,直接进行画面绘制以回应请求,
对于JSF的input与command元件,都有一个immediate属性可以设定,只要将其设定为true,则指定的事件就成为立即事件。
3.JSF Phase 事件
JSF的请求执行到回应,完整的过程会经过六个阶段:
在每个阶段的前后会引发
javax.faces.event.PhaseEvent,如果您想尝试在每个阶段的前后捕捉这个事件,以进行一些处理,则可以实作
javax.faces.event.PhaseListener,并向javax.faces.lifecycle.Lifecycle登记这个 Listener,以有适当的时候通知事件的发生。
PhaseListener有三个必须实作的方法getPhaseId()、beforePhase()与afterPhase()
PhaseId.APPLY_REQUEST_VALUES
PhaseId.PROCESS_VALIDATIONS
PhaseId.UPDATE_MODEL_VALUES
PhaseId.INVOKE_APPLICATION
PhaseId.RENDER_RESPONSE
PhaseId.ANY_PHASE
其中PhaseId.ANY_PHASE指的是任何的阶段转换时,都进行监听。
如例:
package
test;
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;
}
}
在faces-config.xml中向Lifecycle进行注册:
<lifecycle>
<phase-listener>
onlyfun.caterpillar.ShowPhaseListener
</phase-listener>
</lifecycle>
这样你就可以看到请求运行的每一个阶段前后都加上了Log。
具体程序看示例程序。