2011-12-12 169 views
15

這是我的第一個問題,我希望我做對了。使用有狀態會話Bean來跟蹤用戶的會話

我需要在Java EE項目上工作,所以,在開始之前,我試圖做一些簡單的事情,看看我能否做到這一點。

我被困在有狀會話豆

下面是問題: 如何使用SFSB來跟蹤用戶的會話? 我看到的所有例子,最終都將SFSB變爲HttpSession屬性。 但我不明白爲什麼! 我的意思是,如果bean是STATEFUL,爲什麼我必須使用HttpSession來保留它?

是不是EJB容器的任務將正確的SFSB返回給客戶端?

我試過了一個簡單的計數器bean。 不使用會話,兩個不同的瀏覽器具有相同的計數器bean(單擊「增量」更改了它們的值)。 使用會話,我有兩個不同的值,每個對於每個瀏覽器(點擊Firefox上的「增量」,僅添加一個到Firefox的bean)。

但我的老師告訴記者,一個SFSB保持「會話狀態與客戶端」,那麼爲什麼它不只是不使用HttpSession中工作

如果我理解正確,沒有使用HttpSession中SFSB同一個SLSB而不是做呢?

我希望我的問題很清楚,我的英語不是那麼差!

編輯: 我正在登錄系統上工作。 一切都很順利,完成登錄後,它會將我帶到顯示用戶數據的配置文件頁面。 但重新加載頁面會使我的數據消失! 我已經嘗試在登錄時添加HttpSession,但以這種方式進行操作會使數據在註銷後仍然保留!

回答

25

有狀態會話Bean(SFSB)必須與Web環境中的HTTP會話相結合,因爲它是純粹的業務bean,它本身對Web層一無所知。

傳統上,EJB甚至必須存在於它們自己的模塊(EJB模塊)中,如果他們願意,甚至不能訪問Web工件。這是分層系統的一個方面。有關詳細信息,請參見Packaging EJB in JavaEE 6 WAR vs EAR

Stateful Session Beans的原始客戶端是Swing桌面應用程序,它通過二進制協議與遠程EJB服務器進行通信。 Swing應用程序將通過代理/存根對象獲得與遠程有狀態會話Bean的連接。嵌入在此代理中的是服務器可以與特定SFSB關聯的某種ID。通過堅持這個代理對象,Swing客戶端可以重複調用它,並且這些將會轉到同一個bean實例。這將因此在客戶端和服務器之間創建一個會話。

對於Web應用程序,當瀏覽器向Java EE Web應用程序發出初始請求時,它將獲得服務器可以與特定的HTTPSession實例關聯的JSESSIONID。通過堅持這JSESSIONID,瀏覽器可以提供每個後續請求,這將激活相同的http會話服務器端。

所以,這些概念非常相似,但它們不會自動映射到對方。

瀏覽器只獲得JSESSIONID,並且不知道任何SFSB ID。與Swing應用程序不同,瀏覽器與網頁進行通信,而不是直接與Java bean進行通信。

爲了將客戶端的請求映射到特定的有狀態會話bean,EJB容器只關心通過SFSB代理提供的ID。它無法查看該調用是否發生源自Web模塊中的代碼,並且無法/不應該真正訪問任何HTTP上下文。

作爲訪問SFSB的客戶端代碼的web層必須「保留」特定的代理引用。堅持web層中的某些內容通常意味着將其存儲在HTTP會話中。

然而,有一種橋接技術稱爲CDI,可以進行此自動連接。如果您使用CDI的@SessionScoped註釋您的SFSB並通過CDI獲得對SFSB的引用(例如使用@Inject),則不必手動將SFSB放入http會話中。但是,幕後CDI無論如何都會這樣做。

+0

偉大的答案,阿爾詹。不過,我相信你的意思是@SessionScoped在你的回答的最後一段 –

+0

@ Joe.M感謝你發現錯誤;)修正! –

3

您需要定義與@SessionScoped代替@RequestScoped豆(如果你正在尋找的HttpSession的同類解決方案)

@SessionScoped 
public class SessionInfo implements Serializable{ 
    private String name; 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
} 

看一看以下(詳細解釋)

http://www.oracle.com/technetwork/articles/java/cdi-javaee-bien-225152.html