2012-03-07 45 views
6

我試圖@Inject一個@SessionScoped豆使用CDI注入到過濾器在Servlet

@WebFilter("/*") 
public class IdentityFilter implements Filter, Serializable { 

    @Inject 
    private LoginUser loginUser; 
... 

其中LoginUser@SessionScoped

意圖是爲了loginUser代表登錄的用戶的會話。

問題是,我並不總是從當前會話中獲得loginUser,因爲一個會話的LoginUser對象正在與另一個會話共享,所以會發生會話之間的「泄漏」。顯然這不好。

我想知道這是否是因爲Filter對象是單例,或者至少在容器(glassfish)的請求和會話之間重複使用。 (對吧?)

有沒有更好的方法來獲取當前會話的LoginUser對象而不使用Filter上的屬性?

+0

您能粘貼LoginUser代碼嗎?如果你沒有一個沒有參數的非私有構造函數,或者這個類是final的或者有最終的方法,它將不起作用。 – 2012-03-08 18:37:08

+0

感謝Fabricio。我認爲這是好的,它確實需要注射。問題是分享......我想我發現什麼是錯的,會發布。 – Jonathan 2012-03-11 21:53:34

回答

8

我的問題是容器中只有一個過濾器實例,實際上是一個單例。看起來,CDI在第一次使用時將第一個會話級別對象注入到Filter中,然後Filter將永久存儲該引用,即使對於其他會話也是如此。

我發現這個解決方案,注入一個工廠對象(實例),我可以每次都會使用過濾器的運行,以獲得會話實例,即

@WebFilter("/*") 
public class IdentityFilter implements Filter, Serializable { 

     @Inject 
     private Instance<LoginUser> loginUserSource; 

而且在

@Override 
public void doFilter(...) 
     LoginUser login = loginUserSource.get(); 

這似乎解決了我的問題。

謝謝

+4

實際上,CDI使用代理進行工作,這不是實際的LoginUser實例,只要它沒有依賴範圍並滿足我第一條評論的要求,就會被注入。 – 2012-03-12 14:24:30

+2

+1給Fabricio Lemos的答案。 CDI提供代理。這是由CDI規範(適用於所有NormalScoped bean)規定的。請確保您使用的@SessionScoped確實是CDI(javax.enterprise.context.SessionScoped),而不是來自JSF的一個(java.faces.bean.SessionScoped)。如果您的IDE只是從錯誤的包中自動導入註釋,這是一個常見的錯誤。那些JSF範圍從EE6開始就被認爲是遺留的,甚至可能在未來的JSF版本中被棄用。 – struberg 2014-10-22 15:18:59