actionとactionListenerの違い 質問する

actionとactionListenerの違い 質問する

actionとの違いは何ですか?またactionListener、 と はいつ使用すればよいですか?actionactionListener

ベストアンサー1

アクションリスナー

実際のビジネスアクションが実行される前に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 も参照してください。JSF でサポートされていないのに、<f:actionListener> を任意のメソッドにバインドできるのはなぜですか?


アクション

actionビジネス アクションを実行し、必要に応じてナビゲーションを処理する場合に使用します。このメソッドは、ナビゲーション ケースの結果 (ターゲット ビュー) として使用される をaction返すことができます (したがって、返す必要はありません) 。 または の戻り値により、同じページに戻り、現在のビュー スコープが維持されます。空の文字列または同じビュー ID の戻り値の場合も同じページに戻りますが、ビュー スコープが再作成されるため、現在アクティブなビュー スコープ Bean が破棄され、該当する場合は再作成されます。Stringnullvoid

方法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 に現在のページ (前のページではない) を反映させる方法


f:ajax リスナー

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>

<h:inputXxx>Ajax リスナーは、コマンド コンポーネントではあまり役に立ちません。入力コンポーネントや選択コンポーネント/でより役立ちます<h:selectXxx>。コマンド コンポーネントでは、明確さと自己文書化コードの強化のため、actionおよび/または のみを使用してください。さらに、 と同様に、 はナビゲーション結果を返すことをサポートしていません。actionListeneractionListenerf:ajax listener

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

executeおよびrender属性の説明については、PrimeFaces のプロセス/更新と JSF f:ajax の実行/レンダリング属性を理解する


呼び出し順序

は、ビューで宣言されコンポーネントにアタッチされたのと同じ順序で、常に の前に呼び出されます。 は常にアクションactionListenerリスナーの前に呼び出されます。したがって、次の例をご覧くださいactionf: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である場合、それは良くありません。一部のIDEがEL検証を通じて信じさせているのとは反対に、メソッドは を返すこともできます。voidactionvoidPrimeFaces ショーケースこの種の例はactionListener至る所に散見されます。これは確かに間違っています。これを言い訳にして、自分自身でも同じことをしないでください。

ただし、Ajaxリクエストでは、特別な例外ハンドラが必要です。これは、listener属性を使用する<f:ajax>かどうかに関係なく必要です。説明と例については、JSF ajax リクエストにおける例外処理

おすすめ記事