回答:
実際のビジネスアクションが実行される前に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
属性の括弧の重要性に注意してください。これらが存在しない場合javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
、binding
属性はデフォルトでメソッド式ではなく値式として解釈されるため、ELは混乱を招いてをスローします。EL 2.2+スタイルの括弧を透過的に追加すると、値式がメソッド式に変わります。aoも参照してください。JSFでサポートされていない場合に、<f:actionListener>を任意のメソッドにバインドできるのはなぜですか?
action
ビジネスアクションを実行し、必要に応じてナビゲーションを処理する場合に使用します。このaction
メソッドはString
、ナビゲーションケースの結果(ターゲットビュー)として使用されるa を返すことができます(そのため、必須ではありません)。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" />
これは悪い設計を示していることに注意してください:POSTでナビゲートします。これはユーザーでもSEOフレンドリーでもありません。これはすべて、h:commandLinkではなくh:outputLinkを使用する必要がある場合に説明されています。として解決されることになっています
<h:link value="Go to next page" outcome="nextpage" />
JSFでナビゲートする方法も参照してください。URLに現在のページ(前のページではなく)を反映させる方法。
JSF 2.x以降、3つ目の方法があり<f:ajax listener>
ます。
<h:commandXxx ...>
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>
このajaxListener
メソッドには、デフォルトで次のシグネチャがあります。
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
Mojarraでは、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>
execute
およびrender
属性の説明については、PrimeFacesプロセス/更新およびJSF f:ajax実行/レンダリング属性の理解に進んでください。
actionListener
sが常に起動される前に、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>
次の順序でメソッドを呼び出します。
Bean#ajaxListener()
Bean#actionListener()
ActionListenerType#processAction()
Bean#actionListenerBinding()
Bean#setProperty()
Bean#action()
actionListener
特別な例外をサポートしていますAbortProcessingException
。この例外がactionListener
メソッドからスローされた場合、JSFは残りのアクションリスナーとアクションメソッドをスキップし、直接応答をレンダリングします。エラー/例外ページは表示されませんが、JSFはそれを記録します。これは、他の例外がからスローされているときにも暗黙的に行われactionListener
ます。したがって、ビジネス例外の結果としてエラーページによってページをブロックする場合は、確実にaction
メソッドでジョブを実行する必要があります。
メソッドを使用する唯一の理由が同じページに戻るメソッドactionListener
を持つことであるvoid
場合、それは悪いことです。action
方法は完全にも返すことができvoid
、いくつかのIDEを使用して、ELの検証を経て信じてみましょうどのように逆に、。PrimeFacesのショーケースの例にはactionListener
、あらゆる場所でこの種のs が散らばっていることに注意してください。これは確かに間違っています。これを自分自身で行う言い訳として使用しないでください。
ただし、ajaxリクエストでは、特別な例外ハンドラーが必要です。これは、listener
属性を使用するかどうかに関係あり<f:ajax>
ません。説明と例については、JSF ajaxリクエストの例外処理をご覧ください。
actionListener
、によってスローされる例外のデフォルトの処理を変更できるが、それでもビジネスアクションを悪用するactionListener
ための良い言い訳にはならない。
action
対応します。actionListener
二次的なものです。actionListener
必要に応じてs からの例外が伝播される可能性があることを明確にしたかっただけです;)
actionListener
属性で使用する場合、メソッド名は自由に選択できpublic
、同様にそうでなければなりません。processAction
あなたが使用しているときに名前は必須です<f:actionListener type>
型が実装する必要がありますという理由だけで、ActionListener
メソッド名を正確にすることを持っているインタフェースprocessAction
definiedを。
<f:ajax>
コマンドコンポーネントの場合は、を使用する場合でもaction
、ビジネスアクションに属性を使用することを好むことに注意してください。例えば<h:commandButton action="#{bean.businessAction}"><f:ajax/></h:commandButton>
。
BalusCが示したように、はactionListener
デフォルトで例外を飲み込みますが、JSF 2.0ではこれにはもう少しあります。つまり、飲み込むだけでなくログを記録するだけでなく、実際に例外を公開します。
これは、次のような呼び出しによって発生します。
context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(context, exception, source, phaseId)
);
このイベントのデフォルトのリスナーは、ExceptionHandler
Mojarraのリスナーがに設定されてcom.sun.faces.context.ExceptionHandlerImpl
いるリスナーです。この実装は、ログに記録されるAbortProcessingExceptionに関係する場合を除いて、基本的にすべての例外を再スローします。ActionListenerは、クライアントコードによってスローされる例外を、これらが常にログに記録される理由を説明するAbortProcessingExceptionにラップします。
これは、ExceptionHandler
カスタム実装でのfaces-config.xmlにしかし置き換えることができます。
<exception-handlerfactory>
com.foo.myExceptionHandler
</exception-handlerfactory>
グローバルにリッスンする代わりに、単一のBeanがこれらのイベントをリッスンすることもできます。以下はこれの概念の証明です:
@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");
}
}
(これは、通常リスナーをコーディングする方法ではありません。これはデモンストレーションのみを目的としています!)
このようなFaceletからこれを呼び出す:
<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を使用します。
関係を説明するリンクは次のとおりです。
TL; DR:
ActionListener
Sは(複数存在し得る)、それらが前に登録された順序で実行しますaction
長い答え:
事業は、action
一般的にEJBサービスを呼び出し、必要なも別のビューへの最終的な結果および/またはナビゲートを設定した場合、それはあなたが何をしているかではない場合actionListener
のために、より適切なすなわちのときのようなコンポーネントを持つユーザーが相互作用、h:commandButton
またはh:link
彼らができますマネージドBeanメソッドの名前をactionListener
UIコンポーネントの属性でActionListener
渡すか、インターフェイスを実装して実装クラス名をactionListener
UIコンポーネントの属性に渡すことで処理されます。