19

JSF でのカスタム コンポーネントの開発に関して、理解に苦しむことがいくつかあります。これらの質問の目的のために、すべてのカスタム コントロールが値バインディング/式 (リテラル バインディングではない) を使用していると想定できますが、それらの説明にも興味があります。

  1. valuebinding の値はどこで設定しますか? これはデコードで発生するはずですか?または、デコードして別の処理を行ってから、encodeBegin に値を設定する必要がありますか?
  2. 値バインディングから読み取る - 値バインディングからデータを読み取るのと、送信された値から読み取って値バインディングに入れるのはいつですか?
  3. これらすべてに関連して、フォームのアクション リスナーが呼び出されるのはいつですか? JSFライフサイクルページはすべて、さまざまなステップで発生するイベントについて言及していますが、コマンドボタンの単純なリスナーが呼び出されているだけの場合、完全にはわかりません

いくつかの組み合わせを試してみましたが、イベントのライフサイクルの基本的な誤解から来ていると思われるバグを見つけるのは常に困難です。

4

4 に答える 4

20

JSF仕様には、リクエストのライフサイクルを示す非常に優れた図があります。これは、このことを理解するために不可欠です。

手順は次のとおりです。

  • ビューを復元します。UIComponent ツリーが再構築されます。
  • リクエスト値を適用します。編集可能なコンポーネントは、EditableValueHolder を実装する必要があります。このフェーズでは、コンポーネント ツリーをたどり、processDecodesメソッドを呼び出します。コンポーネントが UIData のような複雑なものではない場合、独自のデコードメソッドを呼び出す以外はあまり機能しません。デコードメソッドは、そのレンダラーを見つけてデコードメソッドを呼び出し、それ自体を引数として渡すこと以外は、ほとんど何もしません。送信された値を取得し、 setSubmittedValueを介して設定するのはレンダラーの仕事です。
  • 検証を処理します。このフェーズは、 validate を呼び出すprocessValidators呼び出します。validateメソッドは、送信された値を受け取り、それを任意のコンバーターで変換し、任意のバリデーターで検証し、(データがこれらのテストに合格すると仮定して) setValueを呼び出します。これにより、値がローカル変数として格納されます。このローカル変数は null ではありませんが、getValueへの呼び出しの値バインディングからの値ではなく、返されます。
  • モデル値を更新します。このフェーズはprocessUpdatesを呼び出します。入力コンポーネントでは、これにより updateModel が呼び出され、ValueExpression取得され、それが呼び出されてモデルに値が設定されます。
  • アプリケーションを呼び出します。ボタン イベント リスナーなどがここで呼び出されます (メモリが機能する場合はナビゲーションも同様です)。
  • レスポンスをレンダリングします。ツリーはレンダラーを介してレンダリングされ、状態が保存されます。
  • これらのフェーズのいずれかが失敗した場合 (たとえば、値が無効である場合)、ライフサイクルは Render Response にスキップします。
  • これらのフェーズのほとんどの後に、さまざまなイベントを発生させることができ、必要に応じてリスナーを呼び出します (プロセス検証後の値変更リスナーなど)。

これはイベントのやや簡略化されたバージョンです。詳細については、仕様を参照してください。

なぜ独自の UIComponent を作成しているのか疑問に思います。これは簡単な作業ではなく、JSF アーキテクチャーを正しく理解するには、JSF アーキテクチャーを深く理解する必要があります。カスタム コントロールが必要な場合は、既存の UIComponent (HtmlInputText のように) を同等のレンダラーで拡張する具体的なコントロールを作成することをお勧めします。

汚染が問題にならない場合は、Apache MyFaces の形式でオープンソースの JSF 実装があります。

于 2008-08-29T15:09:23.110 に答える
4

CommandButtonなどのアクションリスナーは、アプリケーションの呼び出しフェーズ中に呼び出されます。これは、最後のレンダリング応答フェーズの前の最後のフェーズです。これは、JSFライフサイクル-図1に示されています。

于 2008-08-29T11:14:15.447 に答える
3

これは、コンポーネントの作成がこのような深く複雑なプロセスである場合に使用した唯一のフレームワークです。.net の世界であろうとなかろうと、他の Web フレームワークのどれもこれをそれほど苦痛に感じさせません。

JSF の背後にある設計上の決定事項のいくつかは、目標を検討すると、もう少し意味があり始めます。JSF はツール化されるように設計されており、IDE の多くのメタデータを公開しています。JSF は Web フレームワークではありません。Web フレームワークとして使用できるMVPフレームワークです。JSF は拡張性と構成性に優れており、アプリケーションごとに実装の 90% を置き換えることができます。

追加の HTML コントロールを挿入したいだけの場合、これらのほとんどは作業を複雑にするだけです。

コンポーネントは、いくつかのinputtext(およびその他)の基本コンポーネントの構成です。

JSP インクルード/ツール ベースのページ フラグメントは要件を満たしていないと思います。

UIComponentELTag.createComponentを使用して UIPanel ベースの複合コントロールを作成し、既存の実装からすべての子を作成することを検討します。(JSP/taglibs を使用していて、他にもいくつかの推測をしていると思います。) 既存の UIPanel レンダラーがどれも機能しない場合は、おそらくカスタム レンダラーが必要になるでしょうが、レンダラーは簡単です。

于 2008-08-29T17:02:07.393 に答える
1

私が見つけた最高の記事はJsf Component Writingです。2については、コンポーネントの値バインディングの値をどこで読み取るか、このようなゲッターがあります。


public String getBar() {  
     if (null != this.bar) {  
         return this.bar ;  
     }  
     ValueBinding _vb = getValueBinding("bar");  
     return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;  
}
  

これはどのようにして getValueBinding に入ったのですか? タグクラスの setProperties メソッドで

  if (bar!= null) {  
         if (isValueReference(bar)) {  
             ValueBinding vb = Util.getValueBinding(bar);  
             foo.setValueBinding("bar", vb);  
         } else {  
             throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");  
         }  
     }  
于 2008-09-16T14:15:43.007 に答える