Session 有状态EJB问题-为所有用户保留一个会话
我对EJB还很陌生。我的EAR应用程序中需要有状态bean。我在ejb模块中创建了简单的有状态会话bean: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++;
@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。更新了答案,谢谢。