JSFがUIコンポーネントの状態をサーバーに保存するのはなぜですか?


108
  1. JSFがサーバー側のUIコンポーネントの状態を保存するのはいつまでですか?UIコンポーネントの状態情報がサーバーメモリから削除されるのはいつですか?アプリケーションにログインしているユーザーがページを移動すると、コンポーネントの状態がサーバーに蓄積され続けますか?

  2. 私は理解していないサーバー上のUIコンポーネントの状態を維持することの利点は何か!?検証/変換されたデータをマネージドBeanに直接渡すだけでは不十分ですか?それを避けることはできますか、それとも避けなければなりませんか?

  3. 数千の同時ユーザーセッションが存在する場合、サーバー側で多くのメモリを消費しませんか?ユーザーが特定のトピックについてブログを投稿できるアプリケーションがあります。このブログはサイズがかなり大きいです。ポストバックまたはブログの表示要求がある場合、この大きなページのデータはコンポーネントの状態の一部として保存されますか? これはメモリを使いすぎます。これは問題ではありませんか?


更新1:

これで、JSFの使用中に状態を保存する必要がなくなりました。高性能のステートレスJSF実装を使用できます。関連する詳細と議論については、このブログこの質問を参照してください。また、JSF仕様に含める未解決の問題として、JSFにステートレスモードを提供するオプションがあります。(PS が便利な機能である場合は、これこれに関する問題に投票することを検討してください。)


アップデート2(2013年2月24日):

素晴らしいニュースクロサギ科2.1.19がで出ているステートレスモード

こちらをご覧ください:

http://weblogs.java.net/blog/mriem/archive/2013/02/08/jsf-going-stateless?force=255

http://java.net/jira/browse/JAVASERVERFACES-2731

http://balusc.blogspot.de/2013/02/stateless-jsf.html

回答:


199

JSFがサーバー側のUIコンポーネントの状態を保存する必要があるのはなぜですか?

HTTPはステートレスで、JSFはステートフルだからです。JSFコンポーネントツリーは、動的な(プログラムによる)変更の影響を受けます。JSFは、フォームがエンドユーザーに表示されたときの正確な状態を知る必要があるだけなので、フォームが送信されたときに元のJSFコンポーネントツリーによって提供された情報に基づいて、JSFライフサイクル全体を正常に処理できます。サーバー。コンポーネントツリーは、要求パラメーター名、必要なコンバーター/バリデーター、バインドされたマネージドBeanプロパティ、およびアクションメソッドに関する情報を提供します。


JSFはいつサーバー側のUIコンポーネントの状態を保存し、UIコンポーネントの状態情報はいつサーバーメモリから削除されるのですか。

これらの2つの質問は同じように要約されているようです。とにかく、これは実装固有であり、状態がサーバーとクライアントのどちらに保存されるかにも依存します。少しまともな実装では、期限切れになったとき、またはキューがいっぱいになったときに削除されます。たとえば、Mojarraの状態保存がセッションに設定されている場合、デフォルトの論理ビュー数は15です。これは、次のコンテキストパラメータで構成できますweb.xml

<context-param>
    <param-name>com.sun.faces.numberOfLogicalViews</param-name>
    <param-value>15</param-value>
</context-param>

その他のMojarra固有のパラメータについてはMojarra FAQも参照してください。この関連する回答はcom.sun.faces.numberOfViewsInSessionとcom.sun.faces.numberOfLogicalViewsです。


アプリケーションにログインしているユーザーがページを移動すると、サーバーにコンポーネントの状態が蓄積され続けますか?

技術的には、実装によって異なります。ページ間ナビゲーション(GETリクエストのみ)について話している場合、Mojarraはセッション中に何も保存しません。ただし、それらがPOSTリクエスト(コマンドリンク/ボタンのあるフォーム)の場合、Mojarraはセッション内の各フォームの状態を最大制限まで保存します。これにより、エンドユーザーは、同じセッションで異なるブラウザータブで複数のフォームを開くことができます。

または、状態保存がクライアントに設定されている場合、JSFはセッションに何も保存しません。これは、次のコンテキストパラメータで実行できますweb.xml

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

次にjavax.faces.ViewState、フォームの名前を持つ非表示の入力フィールドで暗号化された文字列にシリアル化されます。


サーバー側でUIコンポーネントの状態を維持することの利点が何であるかわかりません。検証/変換されたデータをマネージドBeanに直接渡すだけでは不十分ですか?それを回避することはできますか?

JSFの完全性と堅牢性を保証するには、それだけでは不十分です。JSFは、制御の単一のエントリポイントを持つ動的フレームワークです。状態管理がなければ、人は偽装/ハックHTTP特定の方法でリクエスト(例えば、操作できるようになるdisabledreadonlyrenderedJSFは異なる-そして潜在的にhazardful-事をやらせるために、属性)。それはCSRF攻撃やフィッシングにもなりやすいでしょう。


数千の同時ユーザーセッションがある場合、サーバー側でメモリを大量に消費しませんか?ユーザーが特定のトピックについてブログを投稿できるアプリケーションがあります。このブログはサイズがかなり大きいです。ポストバックまたはブログの表示要求がある場合、大きなブログはコンポーネントの状態の一部として保存されます。これはメモリを消費しすぎます。これは問題ではありませんか?

メモリは特に安いです。appserverに十分なメモリを与えるだけです。または、ネットワーク帯域幅の方が安い場合は、状態の保存をクライアント側に切り替えるだけです。最適な一致を見つけるには、ストレステストを行い、予想される同時ユーザーの最大数でWebアプリケーションのプロファイルを作成し、測定された最大メモリの125%〜150%をappserverに割り当てます。

JSF 2.0では、状態管理が大幅に改善されています。これは、(例えば、部分的な状態を保存することが可能ですだけ<h:form>からではなく、全体のもので保存されます<html>最後まですべての方法)。たとえばモハラはそうします。10の入力フィールド(それぞれにラベルとメッセージが含まれる)と2つのボタンを持つ平均的なフォームは、1KB以下しかかかりません。セッションのビューが15の場合、セッションあたり15KB以下にする必要があります。〜1000の同時ユーザーセッションでは、それは15MB以下でなければなりません。

関心は、セッションまたはアプリケーションスコープ内の実際のオブジェクト(管理対象BeanまたはDBエンティティ、あるいはその両方)に集中する必要があります。SQLの代わりにJavaを使用してレコードをフィルタリング/グループ化/配置するセッションスコープBeanのフレーバーで、データベーステーブル全体を不必要にJavaのメモリに複製するコードやプロジェクトをたくさん見ました。約1000レコードの場合、ユーザーセッションあたり10 MBを簡単に超えます。


1
#2を明確にできますか?リクエストごとにコンポーネントツリーを再作成できないのはなぜですか?リクエストとリクエストの間に実際に保存する必要がある状態とその理由は?リクエスト間でコンポーネントツリーを保存する唯一の理由は、パフォーマンスのためです。
Ryan

ここではより集中質問:stackoverflow.com/questions/7349174/...
ライアン

あなたの答えは私には非常に明確でした!JSFのパフォーマンスとスケーラビリティに関する問題は、プログラマーの実装と本質的に関係しています。正しい方法でテクノロジーを使用することを知る必要があります!
Lucas Batistussi

「アプリサーバーに十分なメモリを与えるだけです。」えーっと、何千もの同時ユーザーセッションを話しているのであれば、ここではエンタープライズレベルのことを話しているように見えます。企業内にエンタープライズレベルの機器がある場合、自宅のLinuxボックスでできるように、「アプリサーバーに十分なメモリを与える」ことはできません。
STU

あなたの答えは非常に明確で、それをありがとう。javax.faces.PARTIAL_STATE_SAVINGをtrueに設定すると、JSFフラッシュスコープが消えたのはなぜですか。getFacesContext()。getExternalContext()。getFlash()。put( "buildingId"、buildingId)。
2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.