JSFライフサイクルとカスタムコンポーネント
-
09-06-2019 - |
質問
JSF でのカスタム コンポーネントの開発に関して、理解するのが難しいことがいくつかあります。これらの質問の目的のために、すべてのカスタム コントロールが (リテラル バインディングではなく) 値バインディング/式を使用していると想定できますが、それらについての説明にも興味があります。
- valuebinding の値はどこで設定すればよいですか?これはデコード時に起こるはずですか?それとも、デコードで何か他のことをしてから、encodeBegin に値を設定する必要がありますか?
- 値バインディングからの読み取り - 値バインディングからデータを読み取るのと、submitvalueからそれを読み取り、valuebindingに入れますか?
- これらすべてに関連して、フォーム上のアクション リスナーはいつ呼び出されますか?JSF ライフサイクルのページではすべて、さまざまなステップで発生するイベントについて言及していますが、コマンドボタンの単純なリスナーがいつ呼び出されるのかは完全にはわかりません。
いくつかの組み合わせを試してみましたが、イベントのライフサイクルの基本的な誤解に起因すると思われる、見つけるのが難しいバグが常に発生します。
解決
かなり良い図があります JSF仕様 これはリクエストのライフサイクルを示しています。これを理解するためには不可欠です。
手順は次のとおりです。
- ビューを復元する. 。UIComponent ツリーが再構築されます。
- リクエスト値の適用. 。編集可能なコンポーネントは EditableValueHolder を実装する必要があります。このフェーズでは、コンポーネント ツリーをたどって、 プロセスデコード メソッド。コンポーネントが UIData のような複雑なものではない場合、独自のコンポーネントを呼び出す以外はあまり機能しません。 デコードする 方法。の デコードする このメソッドは、レンダラーを見つけてそのレンダラーを呼び出すこと以外は何も行いません。 デコードする メソッドを呼び出し、それ自体を引数として渡します。送信された値を取得し、それを設定するのはレンダラーの仕事です。 setSubmittedValue.
- プロセスの検証. 。このフェーズで呼び出されるのは、 プロセスバリデーター どちらが電話しますか 検証. 。の 検証 メソッドは送信された値を取得し、コンバーターで変換し、バリデーターで検証して、(データがこれらのテストに合格すると仮定して) 呼び出します。 セット値. 。これにより、値がローカル変数として保存されます。このローカル変数は null ではありませんが、呼び出しの値バインディングからの値ではなく、この変数が返されます。 getValue.
- モデル値の更新. 。このフェーズで呼び出されるのは、 プロセスアップデート. 。入力コンポーネントでは、これは呼び出します モデルの更新 を取得するのは 値式 それを呼び出してモデルに値を設定します。
- アプリケーションの呼び出し. 。ボタン イベント リスナーなどがここで呼び出されます (メモリがあればナビゲーションも同様です)。
- レンダリング応答. 。ツリーはレンダラーを介してレンダリングされ、状態が保存されます。
- これらのフェーズのいずれかが失敗した場合 (例:値が無効である場合)、ライフサイクルはレンダリング応答にスキップします。
- これらのフェーズのほとんどの後にさまざまなイベントを発生させることができ、必要に応じてリスナーを呼び出します (プロセス検証後の値変更リスナーなど)。
これはイベントをやや簡略化したものです。詳細については仕様を参照してください。
なぜ独自の UIComponent を作成するのか疑問です。これは簡単なタスクではなく、適切に実行するには JSF アーキテクチャを深く理解する必要があります。カスタム コントロールが必要な場合は、同等のレンダラを使用して既存の UIComponent (HtmlInputText のように) を拡張する具体的なコントロールを作成することをお勧めします。
汚染が問題にならない場合は、Apache MyFaces の形式でオープンソースの JSF 実装があります。
他のヒント
アクション リスナー。 コマンドボタン, 、中に呼び出されます アプリケーションの呼び出し フェーズ、これは最終フェーズの前の最後のフェーズです。 レンダリング応答 段階。これは次のように示されています JSF ライフサイクル - 図 1.
これは、コンポーネントの作成がこのような深い複雑なプロセスである場所で使用した唯一のフレームワークです。他のWebフレームワークのどれも(.NETの世界であろうとなかろうと)これをとても苦痛にしていません。
JSF の背後にある設計上の決定の一部は、目標を考慮するともう少し意味が分かり始めます。JSF はツールとして使用できるように設計されており、IDE 用に多くのメタデータを公開します。JSF は Web フレームワークではありません。 MVP Webフレームワークとして利用できるフレームワークです。JSF は拡張性と構成可能性が高く、アプリケーションごとに実装の 90% を置き換えることができます。
追加の HTML コントロールを挿入したいだけの場合、これらのほとんどは作業を複雑にするだけです。
コンポーネントは、いくつかのinputText(およびその他の)ベースコンポーネントの構成です。
JSP インクルード/ツールベースのページ フラグメントが要件を満たしていないのではないかと思います。
あなたの使用を検討します UIComponentELTag.createComponent UIPanel ベースを使用して複合コントロールを作成し、そのすべての子を既存の実装から作成します。(JSP/taglibs を使用していると仮定し、他にもいくつかの推測を行っています。) 既存の UIPanel レンダラーが機能しない場合は、おそらくカスタム レンダラーが必要になるでしょうが、レンダラーは簡単です。
私が見つけた最高の記事は JSFコンポーネントの作成, 、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.");
}
}