Session 有状态EJB问题-为所有用户保留一个会话

Session 有状态EJB问题-为所有用户保留一个会话,session,ejb,stateful,Session,Ejb,Stateful,我对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++;

我对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++;
    }
}
我从war模块中的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();
    }
...
}
公共类TestServlet扩展了HttpServlet{ @EJB 试验; 受保护的void processRequest(HttpServletRequest请求、HttpServletResponse响应) 抛出ServletException、IOException{ setContentType(“text/html;charset=UTF-8”); PrintWriter out=response.getWriter(); HttpSession session=request.getSession(true); out.println(“”); out.println(“”); out.println(“”); out.println(“”); out.println(“”); out.println(“+test.getI()+”); out.println(“”); out.println(“”); out.close(); } ... } 当我运行它时,随着浏览器的每次刷新,这个数字会越来越大

0,1,2

但是,当我在另一个浏览器中运行它时,数字不是从0开始,而是从上一个浏览器继续会话。它的行为就像单身汉

3,4,5

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


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

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

您需要创建有状态会话bean的每个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 for injection而不是@EJB。

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

您需要创建有状态会话bean的每个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 for injection而不是@EJB。

谢谢您的回答。我试着做了治疗,但没有效果。我的错误是,我用EJB获取实例,但它应该用Inject。所以现在我很高兴地使用SessionScoped Stateful和injection,它可以工作了。啊,是的,我忘了提到@Inject。更新了答案,谢谢。谢谢你的回答。我试着做了治疗,但没有效果。我的错误是,我用EJB获取实例,但它应该用Inject。所以现在我很高兴地使用SessionScoped Stateful和injection,它可以工作了。啊,是的,我忘了提到@Inject。更新了答案,谢谢。