写了一个简单至极的JSF页面,如下:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<head>
<title>Hello</title>
</head>
<body>
<f:view>
<h:form>
<h:commandButton actionListener="#{testBean.sayHello}" value="Hello!">
<f:setPropertyActionListener target="#{testBean.userName}"
value="zhangsan" />
<f:actionListener type="myex2.lc.MyActionListener"/>
</h:commandButton>
</h:form>
</f:view>
</body>
</html>
对应的Bean如下:
package myex2.lc;
import javax.faces.event.ActionEvent;
public class TestBean {
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void sayHello(ActionEvent evt) {
System.out.println("sayWord: Hello, " + userName);
}
}
控制台上的输出结果会是什么呢?答案如下:
sayWord: Hello, null
MyActionListener: Hello, zhangsan
为什么两个ActionListener(sayHello方法和 <f:actionListener type="myex2.lc.MyActionListener"/>)的输出会不一样?
原因在于<f:setPropertyActionListener>也是一个ActionListener,总共3个ActionListener执行的顺序不同。
正常情况下,attribute中声明的方法ActionListener,总比<f:actionListener>类的ActionListener先执行;
而后<f:actionListener>类的ActionListener再按声明的先后顺序依次执行。
所以在这个例子里面执行的顺序是:#{testBean.sayHello} -> <f:setPropertyActionListener> -> <f:actionListener>。
同时也可看出,对于attribute类的ActionListener,通过<f:setPropertyActionListener>传递参数似乎并不是一个好办法,还需要构建ValueExpression去求值,比较麻烦。
而可以采用<f:attribute>代替,再用ActionEvent的getComponent() -> getAttributes()解析出参数,相对方便一些。
而action属性总是在各类ActionListener执行之后才被调用,因此没有此类干扰。
以上情况,也可推及ValueChangeListener。