24

管理対象Beanの状態とコンポーネントツリーの状態には違いがあるようです。@RequestScoped@SessionScopedなどのアノテーションを使用してマネージドBeanの状態を制御できますが、コンポーネントツリーの状態を保存するかどうかを選択することはできないようです(ただし、サーバーとクライアントのどちらに保存するかは選択できます)。 )。

コンポーネントツリーの状態は、リクエストの処理を支援する一時的なデータ構造として、単一のリクエストの期間中にのみ必要となるようです。リクエストごとに最初から再構築する必要があります。JSF 2.0では、フォームデータのみが保存されるため、部分的な状態保存によって状況が改善されますが、前のリクエストのフォームデータでさえも役立つ理由がわかりません。

アプリケーションがリクエストスコープで管理されたBeanのみを使用する場合、リクエスト間でコンポーネントツリーの状態を保存することは特に意味がありません。アプリケーションにセッションスコープのマネージドBeanがある場合でも、マネージドBeanは状態を保持し、コンポーネントツリーはリクエスト間で状態を保持する必要はないと思います。

4

2 に答える 2

21

JSF 2.0以降、以前の回答に追加して、partial state savingデフォルトで何かが使用されています。

JSF (Facelets) のデフォルトのビュー記述言語は、リクエストごとに元の Facelet からコンポーネント ツリー全体を作成し、対応するタグ属性からコンポーネントを初期化します。次に、状態をマークします。

後続のすべての状態変更はデルタ変更として記憶され、実際に保存されるのはこの状態です。単にそのような変更がなく、ビューステートが空であることが判明する可能性があります (バグのため、状態が完全に空になることはありませんでしたが、最近修正されました。http://java.net/を参照してください)。詳細はjira/browse/JAVASERVERFACES-2203 )

ですから、大きな問題は、空でない場合、実際にこの状態にあるのは何ですか?

BalusC がすでに述べたように、これはコンポーネント ツリーへの動的な変更を保持できます。これらの変更は、バッキング Bean から、または静的コンポーネント内から開始できます。この動的な変更を行うコンポーネントの種類の簡単な例は、データ セット内の実際の列数に基づいて子列コンポーネントを作成するテーブル コンポーネントです。

ビュー ステートのもう 1 つの重要な使用法は、コンポーネント内で変更されたがモデルにプッシュされていない値を記憶することです。これは、スイッチ コンポーネントのスイッチのフリック、ダイヤル コンポーネントのスライダーの移動などです。

特定の例の 1 つは、viewParam初期化に使用した要求パラメーター (GET のクエリ文字列パラメーターまたは顔以外の POST パラメーター) を記憶するコンポーネントです。詳細については、これを参照してください: http://arjan-tijms.omnifaces.org/2011/07/stateless-vs-stateful-jsf-view.html

また、UI の状態を記憶するステートフル コンポーネントと、失敗した変換または検証との強い関係もあります。この場合、UI コンポーネントはユーザーが入力した値を記憶し、変換/検証エラーがあったことを記憶します。

状態のさらに別の用途は最適化です。一部のコンポーネントは、計算にコストがかかると思われる値を計算し、ビュー ステートに格納します。たとえば、UIInput コンポーネントは、最初のポストバックの後にこれを行います。

private boolean validateEmptyFields(FacesContext ctx) {

    if (validateEmptyFields == null) {
        ExternalContext extCtx = ctx.getExternalContext();
        String val = extCtx.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);

        if (val == null) {
            val = (String) extCtx.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
        }
        if (val == null || "auto".equals(val)) {
            validateEmptyFields = isBeansValidationAvailable(ctx);
        } else {
            validateEmptyFields = Boolean.valueOf(val);
        }
    }

    return validateEmptyFields;

}

これvalidateEmptyFieldsがビューステートに保存された後、次のフォーム送信時に再度計算する必要はありません。ユーザーが再計算するか保存するかを選択できるようになれば、改善されるでしょう (よく知られている時空間最適化)。

状態の概念そのものが、初期の概念から Web アプリケーション開発を悩ませてきました。誰もが本質的にステートフルなインタラクションを望んでいますが、それを処理したり考えたりしたいと思う人はほとんどいません。

JSF はここで答えを出そうとしていますが、明らかに完璧ではなく、改善の余地があります。ビューステート(空のビューステートであっても)を復元できるというJSFの主張は面倒な場合がありますが、別の回答で述べたように、CSRFに対する暗黙的な保護を提供します。JSF 2.2 は、より明示的な CSRF 保護を取得する予定です (例: http://arjan-tijms.omnifaces.org/p/jsf-22.html#869を参照)。そのため、将来、ここで何らかの変更が行われる可能性があります。

コンポーネントごとに状態をオフにするオプションがあり、フレームワークが (ASP.NET のように) できない場合に状態を復元するための簡単なフックがあることも役立つ場合があります。

于 2011-10-31T17:45:49.520 に答える
20

コンポーネント ツリーは、最初の要求に応じてプログラムで変更できるためです。これは、フォーム データを処理する必要がある場合は常に、後続の要求で再現できるとは限りません。

また、コンポーネント ツリーにもモデル値が保持されていると考えている印象があります。本当じゃない。モデル値 (マネージド Bean プロパティ) への (式言語による) 参照のみを保持します。ビュー ステートはモデル ステートをコピー/複製/包含しません。これは単なる純粋な UI コンポーネント ツリーです。おそらくあなたの混乱はこれに基づいています。「フォームデータ」という用語は、送信された値およびモデル値として解釈されることに注意してください。

以下も参照してください。

于 2011-09-08T14:49:05.093 に答える