爪哇:
public class MyBean {
...
public Handler getHandler(){
return new Handler(){
public void handle(ActionEvent e){...}
}
}
...
}
public interface Handler{
void handle(ActionEvent e);
}
XHTML:
<h:commandButton ... actionListener="#{myBean.handler.handle}"/>
我在tomcat 6.0环境中。这是java中的常见模式,但似乎不适用于EL方法绑定。我得到一个例外:
javax.faces.event.MethodExpressionActionListener processAction SEVERE): Received 'java.lang.IllegalAccessException' when invoking action listener '#{myBean.handler.handle}' for component 'j_id115'
javax.faces.event.MethodExpressionActionListener processAction SEVERE): java.lang.IllegalAccessException: Class org.apache.el.parser.AstValue can not access a member of class MyBean$1 with modifiers "public"
...
答案 0 :(得分:1)
是的,但是你做错了。
首先,#handle()
- 方法必须声明为public,因为它是接口的公共方法的实现。
public class MyBean {
...
public Handler getHandler(){
return new Handler(){
public void handle(){...}
};
}
}
第二点是,你将Handler称为actionListener,但你想要的是调用#handle() - 方法:
<h:commandButton actionListener="#{myBean.handler.handle}"/>
您还应该从界面(和实现)中的方法签名中省略ActionEvent
public interface Handler {
public void handle();
}
答案 1 :(得分:1)
这比我想的更微妙......
从java中调用内部类中的public方法没有问题:
MyBean myBean = getMyBean();
Handler handler = myBean.getHandler();
handler.handle(event); // OK
使用反射,取决于它是如何完成的。该方法可以声明为(1):
Method getHandlerMethod = MyBean.class.getMethod("getHandler");
Method handleMethod = getHandlerMethod.getReturnType().getMethod("handle", ActionEvent.class);
handleMethod.invoke(handler, event); // OK, invoking declared method works
或者可以按照内部类(2)中的定义调用它:
Method handleMethod = handler.getClass().getMethod("handle", ActionEvent.class);
handleMethod.invoke(handler, event) // throws IllegalAccessException
显然,还有第三种选择,它有效(3):
Method handleMethod = handler.getClass().getDeclaredMethod("handle", ActionEvent.class);
handleMethod.invoke(handler, event) // OK
不幸的是,我的JSF环境(带有JSF mojarra 1.2和icefaces 1.8.2的Tomcat 6.0)实现了方法(2)而不是(3),因此我的例子不起作用。
答案 2 :(得分:0)
如果将handle()方法指定为ActionListener,例如
,它应该可以工作<h:commandButton ... actionListener="#{myBean.handler.handle}"/>
要指定ActionListener接口的实现类,可以使用“f:actionListener”标记,例如
<h:commandButton>
<f:actionListener type="com.bla.SomeActionListenerImplementation" />
</h:commandButton>
但是这在你的情况下不起作用,因为你的MyBean类没有实现ActionListener接口......