与有状态,无状态和单例EJB bean相同的结果
我正在尝试创建@Stateful,@Stateless和@Singleton EJB bean的简单示例,以帮助我更好地理解差异。问题是,当我使用@Stateful,@Stateless或@Singleton注解中的任何一个注释bean时,根本没有区别。与有状态,无状态和单例EJB bean相同的结果
这里是bean:
import javax.ejb.Singleton;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
@Stateful
public class Bean {
private int counter = 0;
public int getCounter(){
return counter++;
}
}
这里是Servlet的客户:
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javaeetutorial.converter.ejb.Bean;
@WebServlet(urlPatterns="/")
public class Client extends HttpServlet{
@EJB
Bean bean;
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html lang=\"en\">");
out.println("<head>");
out.println("<title>test</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet ConverterServlet at " +
request.getContextPath() + "</h1>");
try {
out.println("<form method=\"get\">");
out.println("<input type=\"submit\" value=\"Submit\">");
out.println("</form>");
out.println("<p>" + bean.getCounter() + "</p>");
out.println("<p>" + bean + "</p>");
} finally {
out.println("</body>");
out.println("</html>");
out.close();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
我预期的结果是:
@Statefull - 当每一个不同的客户端按按钮看到从0开始计数
@Singleton - 当任何客户端按e钮只看到一个计数
@Stateless - 我不知道会发生
的问题,你必须是该webservlet被实例化一次(或至少每个请求不是一次,那是你需要清楚地看到有什么区别),所以它是bean实例。因此,使用哪种类型的bean(有状态,无状态,单例)没有区别,因为Bean实例始终依赖于同一个servlet实例。
如果你想使用requestScoped资源,与单注释,你会算多少次已经要求计数器(所有请求共享同一个实例),与状态你会看到多少次客户请求的计数器,并与无状态将取决于。但是,因为计数器是一个状态,所以使用一个无状态bean(查看名称)是没有意义的。你可以理解为无状态的池 ejb,所以每次需要bean时,服务器都会获取无状态池的实例。一个优点是bean的性能,因为它们已经被创建到池中(检查无状态池配置),它们使用起来非常快。
你可以找到更多的信息here。
正是预期的结果是:
@Stateful - 有状态会话Bean有超时,所以你应该从来没有注入一个有状态的会话bean到一个长寿命的对象,如一个servlet。相反,你应该只查看它们并使用它们(可能通过将引用插入到HttpSession中)。预期的结果是bean实例及其计数器将被所有请求共享,并且如果发出并发请求,则每个请求都会阻塞等待对有状态会话bean的访问(尝试向getCounter方法添加睡眠,然后发出请求来自多个浏览器标签/窗口)。如果您在一段时间内没有提出请求,则该bean将被删除,这将导致所有后续请求失败;您可以使用
@StatefulTimeout(value=1, unit=TimeUnit.SECONDS)
轻松观察此情况。@Singleton - bean实例及其计数器将被所有请求共享。默认情况下,singleton使用容器管理的并发性,因此一次只能有一个请求在一个方法中被允许。再次,您可以在getCounter方法中添加一个睡眠来观察这一点。
@Stateless - 根据您的应用程序服务器的池配置,可能会根据并发请求的需要创建多个bean实例,并且可能会跨请求重用bean实例。同样,您可以为getCounter方法添加一个睡眠,并通过多个浏览器选项卡/窗口发出请求来观察这一点。无状态会话bean旨在用于封装其他EJB服务(例如事务,安全性,调度等),因此成员变量只应用于缓存可以使用的状态,而不管客户端如何缓存(例如,缓存对DataSource,UserTransaction等),而不是存储状态。
描述你正在运行的测试 – fantarama