https://stackoverflow.com/questions/3909267/differences-between-action-and-actionlistener

 

actionListener

Use actionListener if you want have a hook before the real business action get executed, e.g. to log it, and/or to set an additional property (by <f:setPropertyActionListener>), and/or to have access to the component which invoked the action (which is available by ActionEvent argument). So, purely for preparing purposes before the real business action gets invoked.

The actionListener method has by default the following signature:

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

And it's supposed to be declared as follows, without any method parentheses:

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

Note that you can't pass additional arguments by EL 2.2. You can however override the ActionEventargument altogether by passing and specifying custom argument(s). The following examples are valid:

<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) {}

Note the importance of the parentheses in the argumentless method expression. If they were absent, JSF would still expect a method with ActionEvent argument.

If you're on EL 2.2+, then you can declare multiple action listener methods via <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() {}

Note the importance of the parentheses in the binding attribute. If they were absent, EL would confusingly throw a javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, because the binding attribute is by default interpreted as a value expression, not as a method expression. Adding EL 2.2+ style parentheses transparently turns a value expression into a method expression. See also a.o. Why am I able to bind <f:actionListener> to an arbitrary method if it's not supported by JSF?


action

Use action if you want to execute a business action and if necessary handle navigation. The actionmethod can (thus, not must) return a String which will be used as navigation case outcome (the target view). A return value of null or void will let it return to the same page and keep the current view scope alive. A return value of an empty string or the same view ID will also return to the same page, but recreate the view scope and thus destroy any currently active view scoped beans and, if applicable, recreate them.

The action method can be any valid MethodExpression, also the ones which uses EL 2.2 arguments such as below:

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

With this method:

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

Note that when your action method solely returns a string, then you can also just specify exactly that string in the action attribute. Thus, this is totally clumsy:

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

With this senseless method returning a hardcoded string:

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

Instead, just put that hardcoded string directly in the attribute:

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

Please note that this in turn indicates a bad design: navigating by POST. This is not user nor SEO friendly. This all is explained in When should I use h:outputLink instead of h:commandLink? and is supposed to be solved as

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

See also How to navigate in JSF? How to make URL reflect current page (and not previous one).


f:ajax listener

Since JSF 2.x there's a third way, the <f:ajax listener>.

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

The ajaxListener method has by default the following signature:

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

In Mojarra, the AjaxBehaviorEvent argument is optional, below works as good.

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

But in MyFaces, it would throw a MethodNotFoundException. Below works in both JSF implementations when you want to omit the argument.

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

Ajax listeners are not really useful on command components. They are more useful on input and select components <h:inputXxx>/<h:selectXxx>. In command components, just stick to actionand/or actionListener for clarity and better self-documenting code. Moreover, like actionListener, the f:ajax listener does not support returning a navigation outcome.

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

For explanation on execute and render attributes, head to Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes.


Invocation order

The actionListeners are always invoked before the action in the same order as they are been declared in the view and attached to the component. The f:ajax listener is always invoked beforeany action listener. So, the following example:

<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>

Will invoke the methods in the following order:

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

Exception handling

The actionListener supports a special exception: AbortProcessingException. If this exception is thrown from an actionListener method, then JSF will skip any remaining action listeners and the action method and proceed to render response directly. You won't see an error/exception page, JSF will however log it. This will also implicitly be done whenever any other exception is being thrown from an actionListener. So, if you intend to block the page by an error page as result of a business exception, then you should definitely be performing the job in the action method.

If the sole reason to use an actionListener is to have a void method returning to the same page, then that's a bad one. The action methods can perfectly also return void, on the contrary to what some IDEs let you believe via EL validation. Note that the PrimeFaces showcase examples are littered with this kind of actionListeners over all place. This is indeed wrong. Don't use this as an excuse to also do that yourself.

In ajax requests, however, a special exception handler is needed. This is regardless of whether you use listener attribute of <f:ajax> or not. For explanation and an example, head to Exception handling in JSF ajax requests.


跳转的几个方法:

You can do it in two ways:

  • Navigation:

Calling an action, with the commandButton component set as ajax false, and the bean method returning a String (as you already have).

xhtml page:

<p:commandButton id="savebutton" ajax="false" value="#{msg['addCategory.save']}" action="#{addCategoryController.doSave()}" />
  • Redirect:

Calling an actionListener, with the commandButton component set as ajax true, with the bean method not returning value, but instead performing itself the redirection to the desired page.

xhtml page:

<p:commandButton id="savebutton" ajax="true" value="#{msg['addCategory.save']}" actionListener="#{addCategoryController.doSave()}" />

java bean:

public void doSave(){
categoryAddEvent.fire(categoryProducer.getSelectedCategory());
FacesContext.getCurrentInstance().getExternalContext().redirect(Pages.LIST_CATEGORIES);
}

 

JSF action actionListner 详解的更多相关文章

  1. JAVAEE学习——struts2_01:简介、搭建、架构、配置、action类详解和练习:客户列表

    一.struts2是什么 1.概念 2.struts2使用优势以及历史 二.搭建struts2框架 1.导包 (解压缩)struts2-blank.war就会看到 2.书写Action类 public ...

  2. Struts2-整理笔记(二)常量配置、动态方法调用、Action类详解

    1.修改struts2常量配置(3种) 第一种 在str/struts.xml中添加constant标签 <struts> <!-- 如果使用使用动态方法调用和include冲突 - ...

  3. Android 广播大全 Intent Action 事件详解

    Android 广播大全 Intent Action 事件详解 投稿:mrr 字体:[增加 减小] 类型:转载 时间:2015-10-20我要评论 这篇文章主要给大家介绍Android 广播大全 In ...

  4. JSF标签大全详解

    1. JSF入门 藉由以下的几个主题,可以大致了解JSF的轮廓与特性,我们来看看网页设计人员与应用程序设计人员各负责什么. 1.1简介JSF Web应用程序的开发与传统的单机程序开发在本质上存在着太多 ...

  5. Action Bar详解

    Action bar是一个标识应用程序和用户位置的窗口功能,并且给用户提供操作和导航模式.在大多数的情况下,当你需要突出展现用户行为或全局导航的activity中使用action bar,因为acti ...

  6. Android Action Bar 详解篇 .

    作者原创,转载请标明出处:http://blog.csdn.net/yuxlong2010 作为Android 3.0之后引入的新的对象,ActionBar可以说是一个方便快捷的导航神器.它可以作为活 ...

  7. struts2的action类详解

    Action类的书写方式 方式1

  8. Action Bar详解(二)

    在Android3.0之后,Google对UI导航设计上进行了一系列的改革,其中有一个非常好用的新功能就是引入的ActionBar,他用于取代3.0之前的标题栏,并提供更为丰富的导航效果. 一.添加A ...

  9. PyQt(Python+Qt)学习随笔:Action功能详解及Designer中的操作方法

    老猿Python博文目录 老猿Python博客地址 一.引言 Qt Designer中的部件栏并没Action相关的部件,Action可以在右侧的Action Editor中编辑,如图: 如果没有出现 ...

随机推荐

  1. MyEclipse配置tomcat报错 - java.lang.UnsupportedClassVersionError: org/apache/lucene/store/Directory : Unsupported major.minor version 51.0

    1 开发Servlet程序时,MyEclipse配置好tomcat与JDK之后,启动时控制台报下列错误: 1 java.lang.UnsupportedClassVersionError: org/a ...

  2. 项目中常用的MySQL 优化

    本文我们来谈谈项目中常用的MySQL优化方法,共19条,具体如下: 一.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我 ...

  3. [FreeBuff]Trojan.Miner.gbq挖矿病毒分析报告

    Trojan.Miner.gbq挖矿病毒分析报告 https://www.freebuf.com/articles/network/196594.html 竟然还有端口转发... 这哥们.. 江民安全 ...

  4. Linux(CentOS7)命令学习摘要

    1. 修改机器名 hostnamectl set-hostname newname 2. hosts主机存放位置 /etc/hosts 3. 安装tigervncserver, 然后使用vncserv ...

  5. C++常用宏

    宏是由 #define 定义而来,在预处理阶段进行宏展开,它的格式是: #define N 2 + 2 // 仅仅是字符串替换 #define N (2 + 2) // 也是字符串 ,但是是(2 + ...

  6. Mermaid js与流程图、甘特图..

    https://mermaidjs.github.io/gantt.html https://github.com/jdbranham/grafana-diagram 用 mermaid 画甘特图 h ...

  7. 如何在TypeScript中使用第三方JavaScript框架

    一.安装typings 使用npm全局安装typings :npm install -g typings 安装成功. 二,搜索资源,支持模糊搜索:typings search base64 三.安装t ...

  8. 如何使用apache自带的ab压力测试工具

    ab是apache自带的一个很好用的压力测试工具,当安装完apache的时候,就可以在bin下面找到ab 1 我们可以模拟100个并发用户,对一个页面发送1000个请求 ./ab -n1000 -c1 ...

  9. Protocol buffers--python 实践(二) protocol buffers vs json

    为什么专门开一个坑,来使用pb.放弃本在各平台上都支持得很好的json而使用pb的一个归根到底的理由,就是希望在保证强类型和跨平台的情况下,能够更轻,更快,更简单.既然是奔着这个目标去的,到底多快我需 ...

  10. 当应用程序不是以UserInteractive 模式运行时显示模式对话框或窗体

    最近在做一个WCF程序的时候,WCF程序老是弹出一个错误“当应用程序不是以UserInteractive 模式运行时显示模式对话框或窗体是无效操作.请指定ServiceNotification或Def ...