1. ホーム
  2. jsf

[解決済み] actionとactionListenerの違い

2022-03-24 20:38:27

質問

とはどのような違いがあるのでしょうか? actionactionListener を使用する必要があります。 actionactionListener ?

解決方法は?

アクションリスナ

使用方法 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+スタイルの括弧を追加すると、透過的に値表現がメソッド表現に変わります。a.o.も参照して下さい。 JSFでサポートされていないのに、なぜ任意のメソッドに <f:actionListener> を結びつけることができるのですか?


アクション

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

action メソッドには、任意の有効な MethodExpression また、以下のようなEL2.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) {
    // ...
}

モジャラでは 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>

の説明については executerender 属性は PrimeFacesのprocess/update属性とJSFのf:ajax execute/render属性を理解する .


起動順序

actionListener は常に呼び出されます 前に その 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 があちこちにあります。これは確かに間違っています。これを言い訳にして、自分も同じことをしないように。

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