有什么区别 actionactionListener, ,我什么时候应该使用 action 相对 actionListener?

有帮助吗?

解决方案

ActionListener

采用 actionListener 如果你想要一个钩子 实际业务措施被执行,例如对其进行记录和/或设置附加属性(通过 <f:setPropertyActionListener>),和/或可以访问调用该操作的组件(可以通过 ActionEvent 争论)。因此,纯粹是为了准备真正的业务行动之前的准备目的。

actionListener 默认情况下,方法具有以下签名:

import javax.faces.event.ActionEvent;
// ...

public void actionListener(ActionEvent event) {
    // ...
}

并且应该说如下所示,没有任何方法括号:

<h:commandXxx ... actionListener="#{bean.actionListener}" />

请注意,您不能通过 额外的 El 2.2的论点。但是,您可以覆盖 ActionEvent 通过传递和指定自定义参数,完全参数。以下示例有效:

<h:commandXxx ... actionListener="#{bean.methodWithoutArguments()}" />
<h:commandXxx ... actionListener="#{bean.methodWithOneArgument(arg1)}" />
<h:commandXxx ... actionListener="#{bean.methodWithTwoArguments(arg1, arg2)}" />
public void methodWithoutArguments() {}
public void methodWithOneArgument(Object arg1) {}
public void methodWithTwoArguments(Object arg1, Object arg2) {}

注意括号中无参数表达式中的重要性。如果他们缺席,JSF仍然期望 ActionEvent 争论。

如果您在EL 2.2+上,则可以通过 <f:actionListener binding>.

<h:commandXxx ... actionListener="#{bean.actionListener1}">
    <f:actionListener binding="#{bean.actionListener2()}" />
    <f:actionListener binding="#{bean.actionListener3()}" />
</h:commandXxx>
public void actionListener1(ActionEvent event) {}
public void actionListener2() {}
public void actionListener3() {}

注意括号中的重要性 binding 属性。如果他们缺席,El会混乱地扔一个 javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, ,因为 binding 默认情况下,属性被解释为值表达式,而不是方法表达式。添加EL 2.2+样式括号透明地将值表达式变成方法表达式。另请参阅AO 我为什么能够约束u003Cf:actionListener>如果JSF不支持任意方法?


行动

采用 action 如果您想执行业务措施,并在必要时处理导航。这 action 方法可以(因此,不得必须)返回 String 将用作导航案例结果(目标视图)。返回值的 null 或者 void 将让它返回同一页面,并保持当前视图范围。空字符串或同一视图ID的返回值也将返回到同一页面,但重新创建视图范围,从而销毁当前活动的视图范围示波器bean,如果适用,请重新创建它们。

action 方法可以是任何有效的 MethodExpression, ,也使用EL 2.2参数,例如以下内容:

<h:commandXxx value="submit" action="#{bean.edit(item)}" />

使用此方法:

public void edit(Item item) {
    // ...
}

请注意,当您的操作方法完全返回字符串时,您也可以准确地指定该字符串 action 属性。因此,这完全笨拙:

<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />

使用这种毫无意义的方法返回一个硬编码的字符串:

public String goToNextpage() {
    return "nextpage";
}

相反,只需将那个硬编码的字符串直接放在属性中:

<h:commandLink value="Go to next page" action="nextpage" />

请注意,这反过来表明了不良设计:通过邮政导航。这不是用户也不是SEO友好。这一切都在 我什么时候应该使用h:outputLink而不是h:commandlink? 并应该解决

<h:link value="Go to next page" outcome="nextpage" />

也可以看看 如何在JSF中导航?如何使URL反映当前页面(而不是先前的页面).


F:Ajax听众

由于JSF 2.X有第三种方式, <f:ajax listener>.

<h:commandXxx ...>
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>

ajaxListener 默认情况下,方法具有以下签名:

import javax.faces.event.AjaxBehaviorEvent;
// ...

public void ajaxListener(AjaxBehaviorEvent event) {
    // ...
}

在莫哈拉, AjaxBehaviorEvent 参数是可选的,下面的作用也很好。

public void ajaxListener() {
    // ...
}

但是在myfaces中,它会抛出 MethodNotFoundException. 。当您想省略参数时,下面在两个JSF实现中都可以使用。

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>

Ajax听众在命令组件上并不是真正有用的。它们在输入和选择组件上更有用 <h:inputXxx>/<h:selectXxx>. 。在命令组件中,只需坚持 action 和/或 actionListener 为了清晰和更好的自我纪念品代码。而且,喜欢 actionListener, , 这 f:ajax listener 不支持返回导航结果。

<h:commandXxx ... action="#{bean.action}">
    <f:ajax execute="@form" render="@form" />
</h:commandXxx>

用于解释 executerender 属性,前往 了解PrimeFaces流程/更新和JSF F:AJAX执行/渲染属性.


调用顺序

actionListeners总是被调用 action 以与视图中声明并附加到组件相同的顺序。这 f:ajax listener 总是被调用 任何动作听众。因此,以下示例:

<h:commandButton value="submit" actionListener="#{bean.actionListener}" action="#{bean.action}">
    <f:actionListener type="com.example.ActionListenerType" />
    <f:actionListener binding="#{bean.actionListenerBinding()}" />
    <f:setPropertyActionListener target="#{bean.property}" value="some" />
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandButton>

将按以下顺序调用这些方法:

  1. Bean#ajaxListener()
  2. Bean#actionListener()
  3. ActionListenerType#processAction()
  4. Bean#actionListenerBinding()
  5. Bean#setProperty()
  6. Bean#action()

异常处理

actionListener 支持一个特殊例外: AbortProcessingException. 。如果这个例外是从 actionListener 方法,然后JSF将跳过任何剩余的动作听众和操作方法,并继续直接呈现响应。您不会看到错误/异常页面,但是JSF会记录下来。每当任何其他例外都从一个 actionListener. 。因此,如果您打算因业务异常而通过错误页面阻止页面,那么您绝对应该在 action 方法。

如果唯一使用的理由 actionListener 是有一个 void 返回同一页面的方法,那是一个不好的方法。这 action 方法也可以完美返回 void, ,与某些IDE相反,您可以通过EL验证来相信。请注意 PrimeFaces展示柜 例如 actionListenerS在所有地方。这确实是错误的。不要以此为借口自己做。

但是,在AJAX请求中,需要一个特殊的例外处理程序。这是不管您是否使用的 listener 属性 <f:ajax> 或不。为了说明和一个例子,请前往 JSF AJAX请求中的异常处理.

其他提示

如Balusc所示, actionListener 默认情况下,吞咽异常,但是在JSF 2.0中,还有更多。也就是说,它不仅吞咽和日志,而且实际上 发布 例外。

这是通过这样的电话发生的:

context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
    new ExceptionQueuedEventContext(context, exception, source, phaseId)
);

此事件的默认听众是 ExceptionHandler 莫哈拉(Mojarra)设置为 com.sun.faces.context.ExceptionHandlerImpl. 。此实现基本上将重新验证任何例外,除非它涉及已记录的abortrocessingexception。 ActionListeners包裹了由客户端代码在这样的流行过程中抛出的例外,该异常解释了为什么始终记录它们的原因。

ExceptionHandler 但是,可以通过自定义实现在faces-config.xml中替换:

<exception-handlerfactory>
   com.foo.myExceptionHandler
</exception-handlerfactory>

单个豆子也可以听这些事件,而不是全球聆听。以下是这样的概念证明:

@ManagedBean
@RequestScoped
public class MyBean {

    public void actionMethod(ActionEvent event) {

        FacesContext.getCurrentInstance().getApplication().subscribeToEvent(ExceptionQueuedEvent.class, new SystemEventListener() {

        @Override
        public void processEvent(SystemEvent event) throws AbortProcessingException {
            ExceptionQueuedEventContext content = (ExceptionQueuedEventContext)event.getSource();
            throw new RuntimeException(content.getException());
        }

        @Override
        public boolean isListenerForSource(Object source) {
            return true;
        }
        });

        throw new RuntimeException("test");
    }

}

(请注意,这不是一个通常应该为听众编码的方式,而是出于演示目的!)

从这样的脸部称呼它:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:body>
        <h:form>
            <h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
        </h:form>
    </h:body>
</html>

将导致显示错误页面。

在调用操作并确定下一页的位置之前,ActionListener首先被触发,并有一个选择修改响应的选项。

如果您在同一页面上有多个按钮,这些按钮应该转到同一位置,但要做稍微不同的事情,则可以为每个按钮使用相同的操作,但是使用不同的ActionListener来处理略有不同的功能。

这是描述这种关系的链接:

http://www.java-samples.com/showtutorial.php?tutorialid=605

tl; dr:

ActionListeners(可以有多个)执行,按照他们注册的顺序执行 action

长答案:

业务 action 通常会调用EJB服务,如有必要,还设置最终结果和/或导航到其他视图,如果您不是您在做什么 actionListener 更合适的IE对于用户与组件进行交互时,例如 h:commandButton 或者 h:link 可以通过传递托管bean方法的名称来处理它们 actionListener UI组件的属性或实现 ActionListener 接口并将实现类名称传递给 actionListener UI组件的属性。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top