1

我对 EJB 很陌生。我的 EAR 应用程序中需要有状态 bean。我在 ejb 模块中创建了简单的有状态会话 bean:

@Stateful
public class Test {

    public Test() {
    }

    private int i;

    @PostConstruct
    public void initialize() {
        i = 0;
    }

    public int getI() {
        return i++;
    }
}

我在战争模块中从 servlet 调用它:

public class TestServlet extends HttpServlet {

    @EJB
    Test test;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        HttpSession session = request.getSession(true);

        out.println("<html>");
        out.println("<head>");
        out.println("<title></title>");            
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>" + test.getI() + "</h1>");
        out.println("</body>");
        out.println("</html>");         
        out.close();
    }
...
}

当我运行它时,每次刷新浏览器,这个数字都会变大。

0, 1, 2, ...

但是当我在另一个浏览器中运行它时,数字不是从 0 开始,而是从前一个浏览器继续会话。它的行为类似于单例。

3, 4, 5, ...

为什么没有创建 bean 的新实例?我尝试将会话 bean 放入 war 模块,或使用 SessionScoped 对其进行注释,但结果是相同的。

你能帮我为每个 http 会话创建一个有状态 bean 的新实例吗?

4

1 回答 1

4

创建一个 servlet 来服务所有请求。您将单个有状态会话 bean 的实例注入到 servlet 中,因此所有请求都将使用同一个有状态会话 bean。注入有状态会话 bean 很少有用。

您需要创建有状态会话 bean 的 per-HttpSession 实例:

// Declare the reference without injection...
@EJB(name="ejb/test" beanInterface=Test.class)
public class TestServlet extends HttpServlet {
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        HttpSession session = request.getSession(true);
        Test bean = session.getAttribute(BEAN);
        if (bean == null) {
            try {
                // ...and then create an instance by looking it up from java:comp/env
                bean = (Test)new InitialContext().lookup("java:comp/env/ejb/test");
            } catch (NamingException ex) { ... }
            session.setAttribute(BEAN, bean);
        }

        ...
    }
}

或者,如果您有 CDI,您可以将有状态会话 bean 标记为 @SessionScoped 并使用 @Inject 而不是 @EJB 进行注入。

于 2012-04-26T14:20:22.603 回答