2009-08-15 35 views
21

私はJ(2)EEとWebアプリケーション開発の世界では初めてですが、その周りを素早くナビゲートし、多くのことを学びます。毎日私にとって新しい発見の素晴らしい航海です。JSFのセッションにデータを保存する

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

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

これを行う方法は、私の懸念がある場所です。 JSPで、クッキーやURLの書き換えや隠れたフォーム変数を使ってクライアント側でオブジェクトを保存するsession.setAttribute("myObj", myObject)を使うことができます。

一方、JSFではセッションスコープのBean、たとえばSessionBean1をSessionBean1プロパティ(例:SessionBean1.setSomeOjb(myObj))として使用します。これは正しいことですか?

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

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

セッションのスコープ付きBeanまたはセッションの要求間のアクセスにオブジェクトを保存するセッションマップを使用することをお勧めしますか?

ありがとうございました。

+1

"リクエストごとにセッションスコープBeanの新しいインスタンスが作成されます"これは完全に間違っています –

答えて

21

一般に、Java EE Webアプリケーションは、セッションデータのクライアント側を保存するとは思われません。サーバー側のセッションが肥大化するのは当然のことですが、大きなリソースとパフォーマンスの問題を引き起こす大きなセッションフットプリントがあり、特にクラスタ化された環境である可能性があります。

私は私はあなたがFacesContext.getExternalContextを(使用できることを読んだあなたは

を参照してくださいどこ知りたいのですが)。のgetSession/getSessionMap()クライアント側でセッション変数を保存することになります。

私はあなたが、これは自分自身に戻ってオブジェクトを送信しません同じ

session.setAttribute("myObj", myObject) 

を使用することができた上で、これは単にHttpSessionオブジェクトへのアクセスを与えること(この点について私を修正)と考えていますクライアントは、サーバーに保持され、通常はクッキーに渡されるいくつかのセッション識別子によってキーされます。

これ以外にも2つの方法があります:JSFやJSPからアクセス可能なサーブレットAPIを使用して、独自の製造元のCookieにデータを明示的に入れることができます。フォームを作成し、セッションデータを渡します。

しかし、これを考慮してください。私が使用するApp Serverの経験則では、1k-4kのHttpSessionは問題にならない傾向があります。それより大きく(そして私はセッション数をメガバイト単位で見てきました)、インフラストラクチャに重点を置いています。あなたがそのサイズのセッションを心配していたなら、Cookieや隠されたフィールドにあるメガバイトのデータを毎回ブラウザに送り返すことを期待していますか?おそらく1k-2kも少し大きいでしょう。

ので推奨:

  1. はそれをシンプルに保ちます。 Session APIまたはそのJSF表現を使用します。

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

クラスタリングについての質問に応答して追加された:要求が戻って同じクラスタメンバーに送信されるように、一般的に

は、クラスタ環境では、我々は、セッションの親和性を有します。しかし、要求が別のサーバーに送信されたときに、(おそらくクラスター・メンバーが失敗した)場合を検討する必要があります。

いくつかのApp Serverベンダーは、サーバー間の直接通信またはセッションをデータベースに永続化することによってセッション複製を提供します。ここでは間接的にオーバーヘッドが発生するため、失敗の

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

私は、ショッピングカートはビジネスにとってかなりの価値があると主張します。それは彼らがお金を費やしたいものを顧客が思慮深く蓄積したことを表しています。ですから、それは永続化されるべきであり、むしろセッションに保持されるべきです。一度それを維持しようと決めたら、多くのクライアントデバイスで統合された経験など、他の面白いシナリオにつながることがわかります。顧客はデスクトップPCで自宅でショッピングを開始しますが、オンラインで購入を完了します。

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

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

+0

あなたは正しいです。私は誤って、セッションオブジェクト全体がセッションマップに保存されていることを理解していました。セッションマップはクライアントに送信され、クッキーまたは隠しフィールドの形式で保存されます。代わりに、それはクライアントに送信されているセッションIDです。私が正しく理解していれば、このセッションIDを使用して、特定のWebセッションのすべての属性を格納しているHttpSessionのインスタンスを取得することができます。私の誤解を指摘してくれてありがとう。 – SibzTer

+0

こんにちは、私はあなたが質問に答えるのに長い時間を持っていることを知っていますが、あなたはクラスター環境について面白いことを言っています。要求に応答するサーバーにセッションが保存されている場合、このタイプのアーキテクチャでセッションを維持するにはどうすればよいですか? – kavain

+1

@ Kavain:優れたJava-EEサーバーは、フェイルオーバーのためにクラスタ内でセッション複製を最適化するオプションを提供します。サーバーをグループで構成できるため、すべてのサーバーがすべてのセッション情報を取得するわけではありません。同じグループに属するものだけ。レプリケーション自体とメモリ使用量のパフォーマンスが向上します。だから100台のサーバで100,000のセッションサイズを持つ1.000.000人のユーザを持つということは、各サーバが100GBのメモリを必要とするわけではありません。 3つのグループに分かれていれば、各サーバーには3 GBだけが必要です。そして、100kのセッションサイズは大きいです... – Kukeltje

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> 

、あなたはexternal contextを経由して、プログラムで「bar」をルックアップすることができます。 JSF2に、宣言を除去することができるとの注釈に置き換える:FYI

@ManagedBean(name="bar") @SessionScoped 
public class Bar { 
... 
+0

私はJSFに触れてから約3年を認める必要があります。当時はセッションスコープのマネージドBeanを使っていました私は当時、何の代替策も考えていなかった。 1つの問題は、私たちがこれをきちんと保ち、徐々にセッションスコープのマネージドBeanを鼓舞したくないということです。これは、慎重に選択されたbean名になる可能性があります。 – djna

14

私は私の同僚と、大学のプロジェクトに取り組んでいますが、GoogleImageラベラーなどのウェブです。 さて、私たちは、ログイン、ログアウトなどのメソッドを持つUserControllerを持っています...

@ManagedBean(name = "userController") 
@SessionScoped 

[OK]これはNetBeansのウィザードが作成するものです。その後、registerメソッド

(我々はXHTMLでフォームの属性を使用した...)私たちはDB内のユーザーを保持して:

セッションの作成および管理の我々の方法がありますセッションに値を追加します。

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

ここで、「現在」はユーザー(もちろんログインしたユーザー)です。 ログイン方法で同じことがあります。私はこれがあなたの役に立てば幸い

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

:私たちが持っているlogoutメソッドで

+2

これは不器用です。 'current'を' UserController'のプロパティとして割り当てて(セッションスコープ内の*既に*であるように)、ログアウト時に 'null'に設定してください(または、' ExternalContext#invalidateSession() 'を実行してください。 //stackoverflow.com/questions/3841361/jsf-http-session-login/3842060#3842060 – BalusC

+0

私のコードを@BalusCと置き換えて投稿を編集しました。「FacesContext context = FacesContext.getCurrentInstance ); FacesContext.getCurrentInstance()。getExternalContext()。invalidateSession(); 'FacesContext.getCurrentInstance()。getExternalContext();}のためのremove(" user "); –

関連する問題