23

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

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

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

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

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

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

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

では、セッション スコープ Bean とセッション マップのどちらを使用して、セッションのリクエスト間のアクセス用にオブジェクトを保存することをお勧めしますか?

ありがとう。

4

3 に答える 3

24

一般に、Java EE Web Apps は、クライアント側でセッション データを保存することを期待しない傾向があります。サーバー側でのセッションの肥大化について心配するのは当然です。見られる一般的な問題は、大きなリソースとパフォーマンスの問題を引き起こす可能性のある巨大なセッション フットプリントを持つことであり、特にクラスタ化された環境で発生する可能性があります。

どこで見れるのか知りたい

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

私は(この点で私を修正してください)これは単に HttpSession オブジェクトへのアクセスを提供し、その上で同じものを使用できると信じています

 session.setAttribute("myObj", myObject)

これ自体はオブジェクトをクライアントに送り返しません。オブジェクトはサーバーに保持され、通常は Cookie で渡される何らかのセッション ID によってキー設定されます。

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

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

したがって、推奨事項:

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

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

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

通常、クラスタ化された環境では、リクエストが同じクラスタ メンバーに送り返されるように、セッション アフィニティがあります。ただし、要求が別のサーバーに送信される場合 (おそらくクラスター メンバーに障害が発生した場合) を考慮する必要があります。

一部の App Server ベンダーは、サーバー間の直接通信を介して、またはセッションをデータベースに永続化することにより、セッションのレプリケーションを提供しています。これには明らかにオーバーヘッドがあるため、価値の低いセッションでは、障害が発生した場合にセッションの損失を受け入れることもあります。

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

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

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

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

于 2009-08-15T16:49:09.060 に答える
15

私は同僚と大学のプロジェクトに取り組んでおり、GoogleImage Labeler のようなウェブです。さて、ログイン、ログアウトなどのメソッドを備えた UserController があり、次のようにセッションをスコープします。

@ManagedBean(name = "userController")
@SessionScoped

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

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

register メソッド(XHTML でフォームの属性を使用します...) で、ユーザーを DB に保持し、セッションに値を追加します。

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

「現在」はユーザーです(もちろん、ログインしているユーザーです)。login メソッドでも同じです。

logout メソッドには次のものがあります。

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

これがお役に立てば幸いです。

于 2011-11-17T13:11:16.357 に答える
2

では、セッション スコープ 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 {
...
于 2009-08-15T19:38:44.150 に答える