簡體   English   中英

在同一會話中多次從另一個SessionScoped bean訪問一個SessionScoped bean創建了一個新實例

[英]Accessing a SessionScoped bean from another SessionScoped bean more than once in same session creates a new instance

我在我的應用程序中遇到一種我不了解的行為。 我有一個Servlet( Servlet1 ),它接受一個請求,使當前會話無效,創建一個新會話,然后將請求重定向到引用@Named @SessionScoped bean( Bean1 )的JSF頁面。 servlet和bean @Inject都使用另一個@SessionScoped bean( SharedBean )。 第一次訪問servlet URL時,一切正常。 但是,第二次訪問URL時,@Named @SessionScoped bean正在創建sharedbean的新實例。

所以我想發生的是:

  1. Servlet1創建一個新會話
  2. Servlet1初始化SharedBean
  3. Bean1訪問SharedBean

第一次訪問servlet URL時,這正確地發生了,但是第二次調用是這樣的:

  1. Servlet1創建一個新會話
  2. Servlet1初始化SharedBean
  3. Bean1 創建一個新的 SharedBean

在我看來,這似乎不是正確的行為。 我知道我在這里遺漏了一些東西,希望有人向我解釋一下。 代碼如下:

Servlet1:

@WebServlet
public class Servlet1 extends HttpServlet
{
    @Inject
    private SharedBean sbean;

    public doGet(HttpServeltRequest request, HttpServletResponse response)
    {
        HttpSession session = request.getSession();
        session.invalidate();
        session             = request.getSession(true);

        this.sbean.initialize();

        response.sendRedirect(newURL);
    }
}

Bean1:

@Named
@SessionScoped
public class Bean1 implements Serializable
{
    @Inject
    private SharedBean sbean;

    public void actionMethod()
    {
        this.sbean.execute(); // New instance being created here on 2nd access!
    }
}

SharedBean:

@SessionScoped
public class SharedBean implements Serializable
{
    public void initialize() { /* do some work */ }
    public void exeucte() { /* do some work */ }
}

因為每次請求servlet時,您都使會話無效。 因此,容器將創建一個新bean或提供另一個實例。 您必須在用戶或其他終結點計算機不活動一段時間后使會話無效。

SessionScoped表示Bean實例對多個請求有效。 但是,您必須確定會話對您的應用程序意味着什么。 在大多數情況下,會話與用戶登錄和注銷的時間相關聯。 因此它由多個請求組成。 因此,會話對於多個請求有效,並且對於不同的Servlet而言是相同的。 會話由Servlet容器(例如Tomcat)管理,並通過ServletContext實例提供會話對象的實例。

每當您的servlet被請求時,您就創建一個新的會話。 這意味着容器僅為此單個請求創建一個ServletContext ,並且始終將您的SharedBean的新bean實例綁定到該上下文實例。

由於評論而更新。

在這種情況下,我不建議讓容器管理bean注入。 因為您永遠不知道何時創建bean實例並將其與SharedBean實例相關聯。 我認為原因是您在servlet請求方法中創建新會話的問題。 在這種情況下, SharedBean的bean實例不能相同,因為容器會創建一個SharedBean的新實例並使綁定到servlet的共享bean實例無效。

在這種情況下, 最好在Servlet中創建SharedBean ,將其作為參數傳遞給會話上下文,然后在Bean中使用SessionContext來獲取SharedBean實例。

由於COMMENT而更新

注入的bean由容器管理。 表示容器負責創建和銷毀bean。 如果創建bean的新實例,則引用(地址)或bean實例與servlet容器分離,並且不再由該容器管理。 因此,共享bean引用不適用於您的托管bean Bean1

由於COMMENT而更新

問題的答案是,您在Servlet方法的doGet方法中創建的SharedBean的實例未傳遞到Servlet容器,因此對於托管Bean Bean1不可用

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM