Jsf action和actionListener之间的区别

Jsf action和actionListener之间的区别,jsf,jsf-2,action,actionlistener,Jsf,Jsf 2,Action,Actionlistener,action和actionListener之间有什么区别,我应该在什么时候使用action和actionListener?在调用action并确定下一页的位置之前,actionListener首先被触发,并有一个修改响应的选项。 如果在同一页面上有多个按钮,这些按钮应位于同一位置,但执行的操作略有不同,则可以对每个按钮使用相同的操作,但使用不同的ActionListener来处理略有不同的功能 以下是描述关系的链接: actionListener 如果您想在执行真正的业务操作之前有一个钩子,请使

action
actionListener
之间有什么区别,我应该在什么时候使用
action
actionListener

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

如果在同一页面上有多个按钮,这些按钮应位于同一位置,但执行的操作略有不同,则可以对每个按钮使用相同的操作,但使用不同的ActionListener来处理略有不同的功能

以下是描述关系的链接:

actionListener 如果您想在执行真正的业务操作之前有一个钩子,请使用
actionListener
,例如记录它,和/或设置附加属性(by),和/或访问调用该操作的组件(通过参数可用)。因此,纯粹是为了在调用真正的业务操作之前做好准备

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

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

public void actionListener(ActionEvent event) {
    // ...
}
import javax.faces.event.AjaxBehaviorEvent;
// ...

public void ajaxListener(AjaxBehaviorEvent event) {
    // ...
}
它应该声明如下,没有任何方法括号:

<h:commandXxx ... actionListener="#{bean.actionListener}" />
请注意无参数方法表达式中括号的重要性。如果它们不存在,JSF仍然希望方法具有
ActionEvent
参数

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
如果您使用的是EL2.2+,那么您可以通过
声明多个操作侦听器方法

请注意
binding
属性中括号的重要性。如果它们不存在,EL会令人困惑地抛出一个
javax.EL.PropertyNotFoundException:在com.example.Bean
类型上找不到属性“actionListener1”,因为
binding
属性默认解释为值表达式,而不是方法表达式。添加EL 2.2+样式的括号可以透明地将值表达式转换为方法表达式。另见a.o


行动 如果要执行业务操作,并在必要时处理导航,请使用
action
操作
方法可以(因此,不必)返回一个
字符串
,该字符串将用作导航案例结果(目标视图)。返回值
null
void
将使其返回到同一页面并保持当前视图范围的活动状态。空字符串或相同视图ID的返回值也将返回到同一页面,但重新创建视图范围,从而销毁任何当前活动的视图范围bean,如果适用,重新创建它们

操作
方法可以是任何有效的方法,也可以是使用EL 2.2参数的方法,例如:


使用此方法:

public void edit(Item item) {
    // ...
}
请注意,当您的操作方法仅返回字符串时,您也可以在
action
属性中精确指定该字符串。因此,这完全是笨拙的:


使用此无意义的方法返回硬编码字符串:

public String goToNextpage() {
    return "nextpage";
}
相反,只需将硬编码字符串直接放入属性:


请注意,这反过来表明了一个糟糕的设计:通过POST导航。这对用户和搜索引擎优化都不友好。所有这些都在中进行了解释,并应作为


另见


f:ajax监听器 自从JSF2.x以来,还有第三种方法,即

在Mojarra中,
AjaxBehaviorEvent
参数是可选的,下面的参数同样适用

public void ajaxListener() {
    // ...
}
但在MyFaces中,它会抛出一个
MethodNotFoundException
。当您想省略参数时,以下两种JSF实现都适用

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
有关
execute
render
属性的说明,请参阅


调用顺序
actionListener
s总是在
action
之前调用,调用顺序与在视图中声明并附加到组件的顺序相同。
f:ajax侦听器始终在任何操作侦听器之前调用。下面的例子:


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

  • Bean#ajaxListener()
  • Bean\actionListener()
  • ActionListenerType#processAction()
  • Bean\actionListenerBinding()
  • Bean#setProperty()
  • Bean\action()

  • 异常处理
    actionListener
    支持特殊异常:。如果此异常是从
    actionListener
    方法引发的,那么JSF将跳过任何剩余的操作侦听器和操作方法,并继续直接呈现响应。您不会看到错误/异常页面,但是JSF会记录它。每当从
    actionListener
    引发任何其他异常时,也会隐式执行此操作。因此,如果您打算通过业务异常导致的错误页面来阻止该页面,那么您肯定应该在
    操作
    方法中执行该作业

    如果使用
    actionListener
    的唯一原因是让
    void
    方法返回到同一页面,那么这是一个糟糕的方法。
    action
    方法也可以完美地返回
    void
    ,这与一些IDE通过EL验证让您相信的相反。请注意,示例中到处都是这种
    actionListener
    s。这的确是错误的。不要以此为借口自己也这么做


    然而,在ajax请求中,需要一个特殊的异常处理程序。这与是否使用
    listener
    属性无关。如BalusC所示,默认情况下,
    actionListener
    会接受异常,但在JSF2.0中,这一点还有一些。也就是说,它不只是吞咽和记录,而是发布异常

    这是通过ca实现的
    <h:commandXxx ...>
        <f:ajax listener="#{bean.ajaxListener}" />
    </h:commandXxx>
    
    import javax.faces.event.AjaxBehaviorEvent;
    // ...
    
    public void ajaxListener(AjaxBehaviorEvent event) {
        // ...
    }
    
    public void ajaxListener() {
        // ...
    }
    
    <h:commandXxx ...>
        <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
    </h:commandXxx>
    
    <h:commandXxx ... action="#{bean.action}">
        <f:ajax execute="@form" render="@form" />
    </h:commandXxx>
    
    context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
        new ExceptionQueuedEventContext(context, exception, source, phaseId)
    );
    
    <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>