actionとactionListenerの違い


回答:


583

actionListener

実際のビジネスアクションが実行される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.Beanbinding属性はデフォルトでメソッド式ではなく値式として解釈されるため、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に現在のページ(前のページではなく)を反映させる方法


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>

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実行/レンダリング属性の理解に進んでください


呼び出し順序

actionListenersが常に起動される前に、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>

次の順序でメソッドを呼び出します。

  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を持つことであるvoid場合、それは悪いことです。action方法は完全にも返すことができvoid、いくつかのIDEを使用して、ELの検証を経て信じてみましょうどのように逆に、。PrimeFacesのショーケースの例にはactionListener、あらゆる場所でこの種のs が散らばっていることに注意してください。これは確かに間違っています。これを自分自身で行う言い訳として使用しないでください。

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


1
actionListenersの例外はデフォルトで飲み込まれますが、JSF 2.0ではこの動作を変更できます。詳細については、以下の私の回答を参照してください。
Arjan Tijms 2010

3
@arjan:JSF 2.0ではactionListener、によってスローされる例外のデフォルトの処理を変更できるが、それでもビジネスアクションを悪用するactionListenerための良い言い訳にはならない。
BalusC 2010

1
実際、ビジネスアクションは要求/応答サイクルのメインの「フロー」にあり、それにのみaction対応します。actionListener二次的なものです。actionListener必要に応じてs からの例外が伝播される可能性があることを明確にしたかっただけです;)
Arjan Tijms

2
@Kawy:actionListener属性で使用する場合、メソッド名は自由に選択できpublic、同様にそうでなければなりません。processActionあなたが使用しているときに名前は必須です<f:actionListener type>型が実装する必要がありますという理由だけで、ActionListenerメソッド名を正確にすることを持っているインタフェースprocessActiondefiniedを。
BalusC 2012

2
@Muhammed:ajaxアクションリスナーは、すべての通常のアクションリスナーの前に呼び出されます。<f:ajax>コマンドコンポーネントの場合は、を使用する場合でもaction、ビジネスアクションに属性を使用することを好むことに注意してください。例えば<h:commandButton action="#{bean.businessAction}"><f:ajax/></h:commandButton>
BalusC 2013年

47

BalusCが示したように、はactionListenerデフォルトで例外を飲み込みますが、JSF 2.0ではこれにはもう少しあります。つまり、飲み込むだけでなくログを記録するだけでなく、実際に例外を公開します。

これは、次のような呼び出しによって発生します。

context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
    new ExceptionQueuedEventContext(context, exception, source, phaseId)
);

このイベントのデフォルトのリスナーは、ExceptionHandlerMojarraのリスナーがに設定されて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>

エラーページが表示されます。


43

アクションが呼び出されて次のページの場所を決定する前に、ActionListenerが最初に発生し、応答を変更するオプションが付いています。

同じページに複数のボタンがあり、同じ場所に移動する必要があるが、動作が少し異なる場合は、ボタンごとに同じアクションを使用できますが、少し異なる機能を処理するために異なるActionListenerを使用します。

関係を説明するリンクは次のとおりです。

http://www.java-samples.com/showtutorial.php?tutorialid=605


3
プラス1、太字はほとんどすべてを表します。
Shirgill Farhan 14

0

TL; DR

ActionListenerSは(複数存在し得る)、それらが前に登録された順序で実行しますaction

長い答え

事業は、action一般的にEJBサービスを呼び出し、必要なも別のビューへの最終的な結果および/またはナビゲートを設定した場合、それはあなたが何をしているかではない場合actionListenerのために、より適切なすなわちのときのようなコンポーネントを持つユーザーが相互作用、h:commandButtonまたはh:link彼らができますマネージドBeanメソッドの名前をactionListenerUIコンポーネントの属性でActionListener渡すか、インターフェイスを実装して実装クラス名をactionListenerUIコンポーネントの属性に渡すことで処理されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.