action和actionListener之间的区别 [英] Differences between action and actionListener
问题描述
action
和actionListener
有什么区别,我什么时候应该使用action
与actionListener
?
What is the difference between action
and actionListener
, and when should I use action
versus actionListener
?
推荐答案
actionListener
如果要在执行真正的业务操作之前之前,请使用actionListener
.进行记录和/或设置其他属性(通过 ActionEvent
参数).因此,纯粹是为了在调用实际业务操作之前进行准备.
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.
actionListener
方法默认具有以下签名:
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}" />
请注意,EL 2.2无法传递 additional 参数.但是,可以通过传递并指定自定义参数来完全覆盖ActionEvent
参数.以下示例是有效的:
Note that you can't pass additional arguments by EL 2.2. You can however override the ActionEvent
argument 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) {}
请注意无参数方法表达式中括号的重要性.如果不存在,JSF仍然希望使用带有ActionEvent
参数的方法.
Note the importance of the parentheses in the argumentless method expression. If they were absent, JSF would still expect a method with ActionEvent
argument.
如果您使用的是EL 2.2+,则可以通过<f:actionListener binding>
声明多个动作侦听器方法.
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() {}
请注意binding
属性中括号的重要性.如果不存在,EL会令人困惑地抛出javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
,因为binding
属性默认情况下被解释为值表达式,而不是方法表达式.添加EL 2.2+样式括号会透明地将值表达式转换为方法表达式.另请参阅为什么是我可以绑定< f:actionListener>到JSF不支持的任意方法?
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
. action
方法可以(因此不是必须)返回String
,它将用作导航案例的结果(目标视图).返回值null
或void
将使其返回同一页面并使当前视图范围保持活动状态.空字符串或相同视图ID的返回值也将返回同一页面,但是将重新创建视图范围,从而销毁任何当前活动的视图范围的bean,并在适用时重新创建它们.
Use action
if you want to execute a business action and if necessary handle navigation. The action
method 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.
action
方法可以是任何有效的 MethodExpression
,也是使用EL 2.2参数的参数,例如:
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)}" />
使用此方法:
public void edit(Item item) {
// ...
}
请注意,当您的操作方法仅返回一个字符串时,您也可以仅在action
属性中指定该字符串.因此,这太笨拙了:
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" />
请注意,这反过来又表明设计不好:通过POST导航.这既不是用户也不是SEO友好. 何时应使用h:outputLink而不是h:commandLink?,并且应该解决为
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" />
另请参见自JSF 2.x以来,还有第三种方法,即<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>
ajaxListener
方法默认具有以下签名:
The ajaxListener
method has by default the following signature:
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
在Mojarra中,AjaxBehaviorEvent
参数是可选的,下面的效果很好.
In Mojarra, the AjaxBehaviorEvent
argument is optional, below works as good.
public void ajaxListener() {
// ...
}
但是在MyFaces中,它将抛出MethodNotFoundException
.当您想省略参数时,下面的方法在这两种JSF实现中均有效.
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侦听器在命令组件上并不是真正有用的.它们在输入和选择组件<h:inputXxx>
/<h:selectXxx>
时更有用.在命令组件中,请坚持使用action
和/或actionListener
以获得清晰性和更好的自记录代码.而且,与actionListener
一样,f:ajax listener
不支持返回导航结果.
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 action
and/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.
actionListener
始终在f:ajax listener
始终在任何动作侦听器之前 调用.因此,下面的示例:
The actionListener
s 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 before any 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:
-
Bean#ajaxListener()
-
Bean#actionListener()
-
ActionListenerType#processAction()
-
Bean#actionListenerBinding()
-
Bean#setProperty()
-
Bean#action()
Bean#ajaxListener()
Bean#actionListener()
ActionListenerType#processAction()
Bean#actionListenerBinding()
Bean#setProperty()
Bean#action()
异常处理
actionListener
支持一个特殊的例外: AbortProcessingException
.如果从actionListener
方法引发此异常,则JSF将跳过所有剩余的动作侦听器和该动作方法,并继续直接呈现响应.您将不会看到错误/异常页面,但是JSF会将其记录下来.每当从actionListener
引发任何其他异常时,也将隐式完成此操作.因此,如果由于业务异常而打算通过错误页面来阻止该页面,那么您肯定应该在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.
如果使用actionListener
的唯一原因是让void
方法返回同一页面,那么那是一个不好的选择.与某些IDE通过EL验证让您相信的相反,action
方法也可以完美地返回void
.请注意, PrimeFaces展示示例在所有地方都充满了这种actionListener
.这确实是错误的.请勿以此为借口自己做.
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 actionListener
s over all place. This is indeed wrong. Don't use this as an excuse to also do that yourself.
但是,在ajax请求中,需要一个特殊的异常处理程序.这与是否使用<f:ajax>
的listener
属性无关.有关说明和示例,请访问 JSF ajax请求中的异常处理.
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.
这篇关于action和actionListener之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!