1

爪哇:

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"
...
4

3 回答 3

1

是的,它可以,但你做错了一些事情。

首先#handle()-method 必须声明为 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();
}
于 2012-11-15T10:53:07.283 回答
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),因此我的示例不起作用。

于 2012-11-15T17:58:53.770 回答
0

如果您将 handle() 方法指定为 ActionListener,它应该可以工作,例如

<h:commandButton ... actionListener="#{myBean.handler.handle}"/>

要指定 ActionListener 接口的实现类,您可以使用“f:actionListener”标签,例如

<h:commandButton>
    <f:actionListener type="com.bla.SomeActionListenerImplementation" />
</h:commandButton>

但这不适用于您的情况,因为您的 MyBean 类没有实现 ActionListener 接口......

于 2012-11-15T10:50:00.753 回答