web-dev-qa-db-ja.com

JSFのセッションへのデータの保存

私はJ(2)EEとWebアプリの開発の世界は初めてですが、それを素早くナビゲートし、多くのことを学んでいます。私にとって毎日が新しい発見の素晴らしい旅です。

現在、Glassfish v2でVisual JSF Woodstockを使用しているプロジェクトに取り組んでいます。私もJSFにかなり慣れています。

要求間でいくつかのオブジェクト(たとえばMyObjectなど)を保存する必要がある場合があります。そして、これまで読んで理解してきたことから、セッションを使用してこれらのオブジェクトを異なるリクエスト間で保存する必要があります。ここまでは順調ですね。

正確にこれを行う方法は、私の懸念があるところです。 JSPでsession.setAttribute("myObj", myObject)を使用して、CookieまたはURLの書き換えまたは非表示のフォーム変数を使用してクライアント側でオブジェクトを保存できることを知っています。

一方、JSFではSessionスコープBean、たとえばSessionBean1を使用し、オブジェクトをSessionBean1プロパティとして保存します(例:SessionBean1.setSomeOjb(myObj))。これはこれでうまくいく方法ですか?

このようにすると、各リクエストがセッションスコープBeanの新しいインスタンスSessionBean1とSessionBean1に保存されたmyObjectインスタンスによって使用されるメモリを作成するため、サーバー側でのメモリ使用率が増加すると推測しています。

クライアント側でセッション変数を保存するFacesContext.getExternalContext().getSession/getSessionMap()を使用できることを読みました。

それでは、セッションスコープBeanまたはセッションマップを使用して、セッションのリクエスト間でアクセスするためのオブジェクトを保存する方法をお勧めしますか?

ありがとう。

23
SibzTer

一般的にJava EE Web Appsは、クライアント側でセッションデータを保存することを期待しない傾向があります。リソースとパフォーマンスの重大な問題を引き起こす可能性のあるフットプリント。特にクラスター環境で発生する可能性があります。

あなたがどこを見ているのか知りたい

クライアント側でセッション変数を保存するFacesContext.getExternalContext()。getSession/getSessionMap()を使用できることを読みました。

私はこれを単純にHttpSessionオブジェクトにアクセスできると信じています(この点で私を修正してください)

 session.setAttribute("myObj", myObject)

これ自体はオブジェクトをクライアントに送信せず、サーバーに保持され、通常はCookieで渡されるセッション識別子によってキー設定されます。

現在、他の2つの手法があります。データを独自の製造元のCookieに明示的に挿入することを選択できます。JSFまたはJSPからアクセスできるサーブレットAPIを使用するか、フォームで非表示フィールドを使用できます。したがって、aorundセッションデータを渡します。

しかし、これを考慮してください。私が使用するApp Serverの経験則では、1k-4kのオーダーのHttpSessionは問題になりません。それよりも大きい(そしてメガバイト単位で測定されるセッションを見たことがある)ことは、インフラストラクチャにストレスを与えます。そのサイズのセッションが心配な場合は、リクエストごとにブラウザにCookieまたは隠しフィールドでメガバイトのデータを送信しますか? 1k-2kでさえ、おそらく少し大きいです。

推奨事項:

  1. 複雑にしないでおく。 Session APIまたはそのJSFマニフェストを使用します。

  2. セッション内のデータ量を制御します。

クラスタリングに関する質問への回答として追加されました:

通常、クラスター化された環境ではセッションアフィニティを使用しているため、要求は同じクラスターメンバーに返送されます。ただし、リクエストが別のサーバーに送信される場合は、ケースを検討する必要があります(クラスターメンバーが失敗した場合など)。

一部のApp Serverベンダーは、直接のサーバー間通信またはセッションをデータベースに永続化することにより、セッションレプリケーションを提供しています-明らかにここにはオーバーヘッドがあります。

セッションデータの価値が高い場合、アプリケーションによって永続化されるべきであり、実際にはビジネスデータであり、そのように扱われるべきであるという議論があります。これには、CloudantやMongoDbなどのNOSQLデータベースがますます使用されています。この場合、エラーが発生した場合にセッションデータを取得できるという認識から、HTTPセッションをキャッシュと考えることができます。

だから、ショッピングカートはビジネスにとってかなりの価値があるかもしれないと主張します。それは、顧客がお金を使いたいと思うものの思慮深い蓄積を表しています。したがって、単にセッションに保持するのではなく、永続化する必要があります。永続化することを決定すると、多くのクライアントデバイスでの統合されたエクスペリエンスなど、他の興味深いシナリオにつながることがわかります。顧客はデスクトップPCで自宅で買い物を開始しますが、オンラインで購入を完了します。

したがって、さらなる原則:

3)。 HTTPセッションがあるからといって、HTTPセッションを使いすぎないでください。データのビジネス価値と、データを永続化する必要があるかどうかを検討してください。

22
djna

私は同僚と大学のプロジェクトに取り組んでいます。GoogleImageLabelerのようなWebです。それで、ログイン、ログアウトなどのメソッドを持つUserControllerがあり、次のようにセッションをスコープします:

@ManagedBean(name = "userController")
@SessionScoped

OK、これはNetBeansのウィザードが作成するものです。

セッションを作成および管理する方法は次のとおりです。

register method(XHTMLでフォームの属性を使用する)で、ユーザーをDBに永続化し、セッションに値を追加します。

FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getSessionMap().put("user", current);

ここで、「current」はユーザーです(もちろんログインしているユーザー)。 ログイン方法でも同じことが言えます。

ログアウト方法で:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

これがあなたのお役に立てば幸いです。

14
Carlos Vega

それでは、セッションスコープBeanまたはセッションマップを使用して、セッションのリクエスト間でアクセスするためのオブジェクトを保存する方法をお勧めしますか?

これら2つのものは、まったく同じ場所にデータを保存します。

<managed-bean>
  <managed-bean-class>foo.Bar</managed-bean-class>
  <managed-bean-name>bar</managed-bean-name>
  <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

式で参照されると、 外部コンテキスト を介してプログラムで「バー」を検索できます。

参考までに、JSF2では、宣言を削除して注釈に置き換えることができます。

@ManagedBean(name="bar") @SessionScoped
public class Bar {
...
2
McDowell