为什么有状态和无状态 bean 的行为方式相反?
Why Stateful and Stateless beans behave in opposite way?
我创建了有状态、无状态和单例 bean 类 并尝试访问它们两个不同的 servlet。 运行 项目在 JBoss 服务器上。
当我从每个 servlet 访问有状态 bean 时,将创建两个不同的 bean 对象并为它们保留不同的状态(数据)。但是无状态 bean 对象在两个 servlet 之间共享。单例 bean 的行为方式也与无状态 bean 相同。
我的问题是为什么有状态和无状态 bean 的行为方式相反? session bean的生命周期和servlet的生命周期一样吗?
FirstServlet.java
@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
StatelessBean statelessBean;
@EJB
StateFullBean statefulBean;
@EJB
SingletonBean singletonBean;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String message = "Beans not injected.";
String beanType = request.getParameter("beanType");
if ("Stateless".equals(beanType)) {
if (statelessBean != null) {
message = statelessBean.getHits();
} else {
message = "Stateless bean not injected.";
}
}
if ("Stateful".equals(beanType)) {
if (statefulBean != null) {
message = statefulBean.getHits();
} else {
message = "Stateful bean not injected.";
}
}
if ("Singleton".equals(beanType)) {
if (singletonBean != null) {
message = singletonBean.getHits();
} else {
message = "Singleton bean not injected.";
}
}
response.setContentType("text/html");
response.getWriter().print("<h1>" + message + "</h1>");
}
}
同样,我又创建了一个 servlet DemoServlet.java。
StateFullBean.java
@Stateful
public class StateFullBean{
int hits=0;
public String getHits() {
hits++;
return "StateFullBean number of hits " + hits;
}
public StateFullBean() {
System.out.println("StateFullBean created.");
}
}
StatelessBean.java
@Stateless
public class StatelessBean{
int hits=0;
public String getHits() {
hits++;
return "StatelessBean number of hits " + hits;
}
public StatelessBean() {
System.out.println("StatelessBean created.");
}
}
SingletonBean.java
@Startup
@Singleton(name="SingletonBean")
public class SingletonBean {
int hits=0;
public SingletonBean() {
System.out.println("SingletonBean created.");
}
public String getHits() {
hits++;
return "Singleton bean number of hits " + hits;
}
}
我是不是漏掉了什么代码?
一切都按规定运行。
无状态 EJB 将调用进一步委托给池中当前可用的实例。显然只有一个未同时使用(尚未),因此所有客户端都有相同的机会访问池中的同一实例。如果您在 servlet 上同时发出更多 HTTP 请求,则不再有可用实例的可能性会增加,并且容器将在池中创建一个新实例。
有状态 EJB 绑定到它的客户端(在您的例子中,是 Web servlet 实例)。换句话说,每个 servlet 都有自己的有状态 EJB 实例,不会在其他地方共享。
单例 bean 在应用程序范围内并在所有客户端之间共享。换句话说,每个 servlet 将共享同一个单例 EJB 实例。
请注意,EJB 上下文中的术语“客户端”和“会话”绝对不同于 WAR 上下文中的术语,这是许多初学者的地方翻倒。 EJB 客户端不是 web 浏览器,而是注入 EJB 的 class 实例(在您的例子中,是 web servlet 实例)。 EJB 会话不是 HTTP 会话,而是 EJB 客户端会话。
另请参阅:
- Why Stateless session beans?
- When using @EJB, does each managed bean get its own @EJB instance?
我创建了有状态、无状态和单例 bean 类 并尝试访问它们两个不同的 servlet。 运行 项目在 JBoss 服务器上。
当我从每个 servlet 访问有状态 bean 时,将创建两个不同的 bean 对象并为它们保留不同的状态(数据)。但是无状态 bean 对象在两个 servlet 之间共享。单例 bean 的行为方式也与无状态 bean 相同。
我的问题是为什么有状态和无状态 bean 的行为方式相反? session bean的生命周期和servlet的生命周期一样吗?
FirstServlet.java
@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
StatelessBean statelessBean;
@EJB
StateFullBean statefulBean;
@EJB
SingletonBean singletonBean;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String message = "Beans not injected.";
String beanType = request.getParameter("beanType");
if ("Stateless".equals(beanType)) {
if (statelessBean != null) {
message = statelessBean.getHits();
} else {
message = "Stateless bean not injected.";
}
}
if ("Stateful".equals(beanType)) {
if (statefulBean != null) {
message = statefulBean.getHits();
} else {
message = "Stateful bean not injected.";
}
}
if ("Singleton".equals(beanType)) {
if (singletonBean != null) {
message = singletonBean.getHits();
} else {
message = "Singleton bean not injected.";
}
}
response.setContentType("text/html");
response.getWriter().print("<h1>" + message + "</h1>");
}
}
同样,我又创建了一个 servlet DemoServlet.java。
StateFullBean.java
@Stateful
public class StateFullBean{
int hits=0;
public String getHits() {
hits++;
return "StateFullBean number of hits " + hits;
}
public StateFullBean() {
System.out.println("StateFullBean created.");
}
}
StatelessBean.java
@Stateless
public class StatelessBean{
int hits=0;
public String getHits() {
hits++;
return "StatelessBean number of hits " + hits;
}
public StatelessBean() {
System.out.println("StatelessBean created.");
}
}
SingletonBean.java
@Startup
@Singleton(name="SingletonBean")
public class SingletonBean {
int hits=0;
public SingletonBean() {
System.out.println("SingletonBean created.");
}
public String getHits() {
hits++;
return "Singleton bean number of hits " + hits;
}
}
我是不是漏掉了什么代码?
一切都按规定运行。
无状态 EJB 将调用进一步委托给池中当前可用的实例。显然只有一个未同时使用(尚未),因此所有客户端都有相同的机会访问池中的同一实例。如果您在 servlet 上同时发出更多 HTTP 请求,则不再有可用实例的可能性会增加,并且容器将在池中创建一个新实例。
有状态 EJB 绑定到它的客户端(在您的例子中,是 Web servlet 实例)。换句话说,每个 servlet 都有自己的有状态 EJB 实例,不会在其他地方共享。
单例 bean 在应用程序范围内并在所有客户端之间共享。换句话说,每个 servlet 将共享同一个单例 EJB 实例。
请注意,EJB 上下文中的术语“客户端”和“会话”绝对不同于 WAR 上下文中的术语,这是许多初学者的地方翻倒。 EJB 客户端不是 web 浏览器,而是注入 EJB 的 class 实例(在您的例子中,是 web servlet 实例)。 EJB 会话不是 HTTP 会话,而是 EJB 客户端会话。
另请参阅:
- Why Stateless session beans?
- When using @EJB, does each managed bean get its own @EJB instance?