質問

違いは何ですか actionactionListener, 、いつ使用する必要がありますか actionactionListener?

役に立ちましたか?

解決

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.Bean, 、 なぜなら binding 属性は、デフォルトでは、メソッド式としてではなく、値式として解釈されます。 EL 2.2+スタイルの括弧を追加すると、値式がメソッド式に変わります。 AOも参照してください なぜ私はバインドできるのですかu003Cf:actionListener>JSFによってサポートされていない場合は、任意の方法に?


アクション

使用する action ビジネスアクションを実行し、必要に応じてナビゲーションを処理する場合。 action メソッドは(したがって、必要ではない)を返すことができます String ナビゲーションケースの結果(ターゲットビュー)として使用されます。の返品値 null また void 同じページに戻り、現在のビュースコープを生かし続けます。空の文字列または同じビューIDの返品値も同じページに戻りますが、ビュースコープを再作成するため、現在アクティブなビュースコープ豆を破壊し、該当する場合はそれらを再作成します。

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

これは、悪いデザインを示していることに注意してください:投稿ごとにナビゲートします。これはユーザーでも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) {
    // ...
}

モハラで、 AjaxBehaviorEvent 引数はオプションであり、以下はうまく機能します。

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

しかし、myfacesでは、aを投げます 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>

説明のために executerender 属性、に向かいます PrimeFaces Process/Updateと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. 。この例外がanからスローされている場合 actionListener メソッド、JSFは残りのアクションリスナーとアクションメソッドをスキップし、応答を直接レンダリングするために進みます。ただし、エラー/例外ページは表示されませんが、JSFはログに記録します。これはまた、他の例外がからスローされているときはいつでも暗黙的に行われます actionListener. 。したがって、ビジネスの例外の結果としてエラーページでページをブロックする場合は、間違いなくジョブを実行する必要があります。 action 方法。

唯一の理由が使用する場合 actionListener を持っていることです void 同じページに戻る方法、それは悪いものです。 action 方法は完全に戻ることもできます void, 、一部のIDEがあなたがELの検証を介してあなたに信じさせたものとは反対に。に注意してください PrimeFacesショーケース この種の例には散らばっています actionListenersすべての場所で。これは確かに間違っています。これを言い訳として使用して、自分でそれを行わないでください。

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

他のヒント

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に関係する場合を除き、任意の例外をreります。 ActionListenersこのようなAbortProcessingExceptionでクライアントコードによってスローされる例外をラップし、これらが常にログに記録されている理由を説明します。

これ ExceptionHandler ただし、faces-config.xmlでカスタム実装で置き換えることができます。

<exception-handlerfactory>
   com.foo.myExceptionHandler
</exception-handlerfactory>

グローバルに聞く代わりに、単一の豆もこれらのイベントを聞くことができます。以下は、これの概念の証明です。

@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");
    }

}

(これは通常、リスナーをコードする方法ではなく、これはデモンストレーションのためだけのものではありません!)

このようなフェイスラットからこれを呼び出します:

<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を使用して、わずかに異なる機能を処理します。

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

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

tl; dr:

ActionListeners(複数の存在)実行前に登録された順序で実行 action

長い答え:

ビジネス action 通常、EJBサービスを呼び出し、必要に応じて最終結果を設定し、/またはそれがあなたがしていることではない場合は別のビューにナビゲートします actionListener ユーザーがコンポーネントと対話する場合、より適切です。 h:commandButton また h:link それらは、管理されたBeanメソッドの名前を渡すことで処理できます actionListener UIコンポーネントの属性または実装する ActionListener インターフェイスと実装クラス名をに渡します actionListener UIコンポーネントの属性。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top