无状态和有状态企业Java Bean

时间:2023-01-18 22:25:41

I am going through the Java EE 6 tutorial and I am trying to understand the difference between stateless and stateful session beans. If stateless session beans do not retain their state in between method calls, why is my program acting the way it is?

我正在阅读Java EE 6教程,我试图理解无状态和有状态会话bean之间的区别。如果无状态会话bean在方法调用之间不保持状态,为什么我的程序按照它的方式运行?

package mybeans;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;

@LocalBean
@Stateless
public class MyBean {

    private int number = 0;

    public int getNumber() {
        return number;
    }

    public void increment() {
        this.number++;
    }
}

The client

客户端

import java.io.IOException;
import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;
import mybeans.MyBean;
import java.io.PrintWriter;

@WebServlet(name = "ServletClient", urlPatterns = { "/ServletClient" })
public class ServletClient extends HttpServlet {
    private static final long serialVersionUID = 1L;

    @EJB
    MyBean mybean;

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        PrintWriter out = response.getWriter();
        mybean.increment();
        out.println(mybean.getNumber());
    }

}

I was expecting getNumber to return 0 every time but it is returning 1 and reloads of the servlet in my browser increase it more. The problem is with my understanding of how stateless session beans work and not with the libraries or application server, of course. Can somebody give me a simple hello world type example of a stateless session bean that behaves differently when you change it to stateful?

我希望getNumber每次返回0,但它返回1并且在我的浏览器中重新加载servlet会增加更多。当然,问题在于我对无状态会话bean的工作方式的理解,而不是对库或应用程序服务器的理解。有人可以给我一个简单的hello world类型的无状态会话bean示例,当您将其更改为有状态时,其行为会有所不同吗?

6 个解决方案

#1


88  

The important difference is not private member variables, but associating state with a particular user (think "shopping cart").

重要的区别不是私有成员变量,而是将状态与特定用户相关联(想想“购物车”)。

The stateful piece of stateful session bean is like the session in servlets. Stateful session beans allow your app to still have that session even if there isn't a web client. When the app server fetches a stateless session bean out of the object pool, it knows that it can be used to satisfy ANY request, because it's not associated with a particular user.

有状态会话bean的状态就像servlet中的会话一样。即使没有Web客户端,有状态会话bean也允许您的应用仍然拥有该会话。当应用服务器从对象池中取出无状态会话bean时,它知道它可以用于满足任何请求,因为它不与特定用户相关联。

A stateful session bean has to be doled out to the user that got it in the first place, because their shopping cart info should be known only to them. The app server ensures that this is so. Imagine how popular your app would be if you could start shopping and then the app server gave your stateful session bean to me when I came along!

有状态会话bean必须首先发送给获得它的用户,因为他们的购物车信息应该只为他们所知。应用服务器确保这样做。想象一下,如果您可以开始购物,那么您的应用程序会有多受欢迎,然后当我出现时,应用服务器会向您发送有状态会话bean!

So your private data member is indeed "state", but it's not "shopping cart". Try to redo your (very good) example to make it so the incremented variable is associated with a particular user. Increment it, create a new user, and see if they can still see the incremented value. If done correctly, every user should see just their version of the counter.

所以你的私人数据成员确实是“州”,但它不是“购物车”。尝试重做你的(非常好的)示例,使增量变量与特定用户相关联。增加它,创建一个新用户,看看他们是否仍然可以看到递增的值。如果操作正确,每个用户都应该只看到他们的计数器版本。

#2


127  

Stateless Session Beans (SLSB) are not tied to one client and there is no guarantee for one client to get the same instance with each method invocation (some containers may create and destroy beans with each method invocation session, this is an implementation-specific decision, but instances are typically pooled - and I don't mention clustered environments). In other words, although stateless beans may have instance variables, these fields are not specific to one client, so don't rely on them between remote calls.

无状态会话Bean(SLSB)不依赖于一个客户端,并且无法保证一个客户端在每次方法调用时获取相同的实例(某些容器可能会在每个方法调用会话中创建和销毁bean,这是特定于实现的决策,但实例通常是合并的 - 我没有提到集群环境)。换句话说,尽管无状态bean可能具有实例变量,但这些字段并非特定于一个客户端,因此不要在远程调用之间依赖它们。

In contrast, Stateful Session Beans (SFSB) are dedicated to one client for their entire life, there is no swapping or pooling of instances (it may be evicted from memory after passivation to save resources but that's another story) and maintain conversational state. This means that the instance variables of the bean can keep data relative to the client between method invocations. And this makes possible to have interdependent method calls (changes made by one method affect subsequent method calls). Multi-step processes (a registration process, a shopping cart, a booking process...) are typical use cases for SFSB.

相比之下,有状态会话Bean(SFSB)在其整个生命中专门用于一个客户端,没有交换或汇集实例(可能在钝化之后从内存中逐出以节省资源但这是另一个故事)并保持会话状态。这意味着bean的实例变量可以在方法调用之间保持相对于客户端的数据。这使得相互依赖的方法调用成为可能(一种方法所做的更改会影响后续的方法调用)。多步骤流程(注册流程,购物车,预订流程......)是SFSB的典型用例。

One more thing. If you are using SFSB, then you must avoid injecting them into classes that are multithreaded in nature, such as Servlets and JSF managed beans (you don't want it to be shared by all clients). If you want to use SFSB in your web application, then you need to perform a JNDI lookup and store the returned EJB instance in the HttpSession object for future activity. Something like that:

还有一件事。如果您正在使用SFSB,那么您必须避免将它们注入到多线程的类中,例如Servlet和JSF托管bean(您不希望它被所有客户端共享)。如果要在Web应用程序中使用SFSB,则需要执行JNDI查找并将返回的EJB实例存储在HttpSession对象中以供将来活动。像这样的东西:

try {
    InitialContext ctx = new InitialContext();
    myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean");
    session.setAttribute("my_stateful", myStateful);
} catch (Exception e) {
    // exception handling
}

#3


16  

Stateless and stateful in this context don't mean quite what you might expect.

在这种情况下,无国籍和有状态并不意味着你所期望的。

Statefulness with EJBs refers to what I call conversational state. The classic example is a flight booking. If it consists of three steps:

EJB的有状态是指我称之为会话状态。典型的例子是航班预订。如果它包含三个步骤:

  • Reserve seat
  • 预备座位
  • Charge credit card
  • 收取信用卡
  • Issue Ticket
  • 发行票证

Imagine each of those is a method call to a session bean. A stateful session bean can maintain this kind of conversation so it remembers what happens between calls.

想象一下,每个都是对会话bean的方法调用。有状态会话bean可以维护这种对话,因此它会记住调用之间发生的事情。

Stateless session beans don't have such capacity for conversational state.

无状态会话bean没有这种会话状态容量。

Global variables inside a session bean (stateless or stateful) are something else entirely. Stateful session beans will have a pool of beans created (since a bean can only be used in one conversation at a time) whereas stateless sesion beans will often only have one instance, which will make the global variable works, but I don't think this is necessarily guaranteed.

会话bean(无状态或有状态)中的全局变量完全是另一回事。有状态会话bean将创建一个bean池(因为bean一次只能在一个对话中使用),而无状态sesion bean通常只有一个实例,这将使全局变量起作用,但我不认为这必然得到保证。

#4


4  

This thing happen because the container only has one bean instance in the pool that is being reused for all calls. If you run the clients in parallel you will see a different result because the container will create more bean instances in the pool.

发生这种情况是因为容器在池中只有一个bean实例,它被重用于所有调用。如果并行运行客户端,您将看到不同的结果,因为容器将在池中创建更多Bean实例。

#5


3  

The major differences between the two major types of session beans are:

两种主要类型的会话bean之间的主要区别是:

Stateless Beans

无国籍豆

  1. Stateless Session Beans are the ones which have no conversational state with the client which has called its methods. For this reason they can create a pool of objects which can be used to interact with multiple clients.
  2. 无状态会话Bean是与调用其方法的客户端没有会话状态的会话。因此,他们可以创建一个对象池,可用于与多个客户端进行交互。
  3. Performance wise stateless beans are better since they don't have states per client.
  4. 性能明智的无状态bean更好,因为它们没有每个客户端的状态。
  5. They can handle multiple requests from multiple clients in parallel.
  6. 他们可以并行处理来自多个客户端的多个请求。

Stateful Beans

有状态的豆子

  1. Stateful session beans can maintain the conversational state with multiple clients at a time and the task is not shared between the clients.
  2. 有状态会话bean可以一次维护多个客户端的会话状态,并且不在客户端之间共享任务。
  3. After the session is completed the state is not retained.
  4. 会话结束后,不保留状态。
  5. The container can serialize and store the state as a stale state for future use. This is done to save resources of the application server and to support bean failures.
  6. 容器可以将状态序列化并存储为陈旧状态以供将来使用。这样做是为了节省应用程序服务器的资源并支持bean故障。

#6


2  

It has good answers. I would like to add small answer. Stateless Bean should not used to hold any client data. It should be used to "to model actions or processes that can be done in one shot".

它有很好的答案。我想补充一点小问题。无状态Bean不应该用于保存任何客户端数据。它应该用于“模拟可以一次完成的动作或过程”。

#1


88  

The important difference is not private member variables, but associating state with a particular user (think "shopping cart").

重要的区别不是私有成员变量,而是将状态与特定用户相关联(想想“购物车”)。

The stateful piece of stateful session bean is like the session in servlets. Stateful session beans allow your app to still have that session even if there isn't a web client. When the app server fetches a stateless session bean out of the object pool, it knows that it can be used to satisfy ANY request, because it's not associated with a particular user.

有状态会话bean的状态就像servlet中的会话一样。即使没有Web客户端,有状态会话bean也允许您的应用仍然拥有该会话。当应用服务器从对象池中取出无状态会话bean时,它知道它可以用于满足任何请求,因为它不与特定用户相关联。

A stateful session bean has to be doled out to the user that got it in the first place, because their shopping cart info should be known only to them. The app server ensures that this is so. Imagine how popular your app would be if you could start shopping and then the app server gave your stateful session bean to me when I came along!

有状态会话bean必须首先发送给获得它的用户,因为他们的购物车信息应该只为他们所知。应用服务器确保这样做。想象一下,如果您可以开始购物,那么您的应用程序会有多受欢迎,然后当我出现时,应用服务器会向您发送有状态会话bean!

So your private data member is indeed "state", but it's not "shopping cart". Try to redo your (very good) example to make it so the incremented variable is associated with a particular user. Increment it, create a new user, and see if they can still see the incremented value. If done correctly, every user should see just their version of the counter.

所以你的私人数据成员确实是“州”,但它不是“购物车”。尝试重做你的(非常好的)示例,使增量变量与特定用户相关联。增加它,创建一个新用户,看看他们是否仍然可以看到递增的值。如果操作正确,每个用户都应该只看到他们的计数器版本。

#2


127  

Stateless Session Beans (SLSB) are not tied to one client and there is no guarantee for one client to get the same instance with each method invocation (some containers may create and destroy beans with each method invocation session, this is an implementation-specific decision, but instances are typically pooled - and I don't mention clustered environments). In other words, although stateless beans may have instance variables, these fields are not specific to one client, so don't rely on them between remote calls.

无状态会话Bean(SLSB)不依赖于一个客户端,并且无法保证一个客户端在每次方法调用时获取相同的实例(某些容器可能会在每个方法调用会话中创建和销毁bean,这是特定于实现的决策,但实例通常是合并的 - 我没有提到集群环境)。换句话说,尽管无状态bean可能具有实例变量,但这些字段并非特定于一个客户端,因此不要在远程调用之间依赖它们。

In contrast, Stateful Session Beans (SFSB) are dedicated to one client for their entire life, there is no swapping or pooling of instances (it may be evicted from memory after passivation to save resources but that's another story) and maintain conversational state. This means that the instance variables of the bean can keep data relative to the client between method invocations. And this makes possible to have interdependent method calls (changes made by one method affect subsequent method calls). Multi-step processes (a registration process, a shopping cart, a booking process...) are typical use cases for SFSB.

相比之下,有状态会话Bean(SFSB)在其整个生命中专门用于一个客户端,没有交换或汇集实例(可能在钝化之后从内存中逐出以节省资源但这是另一个故事)并保持会话状态。这意味着bean的实例变量可以在方法调用之间保持相对于客户端的数据。这使得相互依赖的方法调用成为可能(一种方法所做的更改会影响后续的方法调用)。多步骤流程(注册流程,购物车,预订流程......)是SFSB的典型用例。

One more thing. If you are using SFSB, then you must avoid injecting them into classes that are multithreaded in nature, such as Servlets and JSF managed beans (you don't want it to be shared by all clients). If you want to use SFSB in your web application, then you need to perform a JNDI lookup and store the returned EJB instance in the HttpSession object for future activity. Something like that:

还有一件事。如果您正在使用SFSB,那么您必须避免将它们注入到多线程的类中,例如Servlet和JSF托管bean(您不希望它被所有客户端共享)。如果要在Web应用程序中使用SFSB,则需要执行JNDI查找并将返回的EJB实例存储在HttpSession对象中以供将来活动。像这样的东西:

try {
    InitialContext ctx = new InitialContext();
    myStateful = (MyStateful)ctx.lookup("java:comp/env/MyStatefulBean");
    session.setAttribute("my_stateful", myStateful);
} catch (Exception e) {
    // exception handling
}

#3


16  

Stateless and stateful in this context don't mean quite what you might expect.

在这种情况下,无国籍和有状态并不意味着你所期望的。

Statefulness with EJBs refers to what I call conversational state. The classic example is a flight booking. If it consists of three steps:

EJB的有状态是指我称之为会话状态。典型的例子是航班预订。如果它包含三个步骤:

  • Reserve seat
  • 预备座位
  • Charge credit card
  • 收取信用卡
  • Issue Ticket
  • 发行票证

Imagine each of those is a method call to a session bean. A stateful session bean can maintain this kind of conversation so it remembers what happens between calls.

想象一下,每个都是对会话bean的方法调用。有状态会话bean可以维护这种对话,因此它会记住调用之间发生的事情。

Stateless session beans don't have such capacity for conversational state.

无状态会话bean没有这种会话状态容量。

Global variables inside a session bean (stateless or stateful) are something else entirely. Stateful session beans will have a pool of beans created (since a bean can only be used in one conversation at a time) whereas stateless sesion beans will often only have one instance, which will make the global variable works, but I don't think this is necessarily guaranteed.

会话bean(无状态或有状态)中的全局变量完全是另一回事。有状态会话bean将创建一个bean池(因为bean一次只能在一个对话中使用),而无状态sesion bean通常只有一个实例,这将使全局变量起作用,但我不认为这必然得到保证。

#4


4  

This thing happen because the container only has one bean instance in the pool that is being reused for all calls. If you run the clients in parallel you will see a different result because the container will create more bean instances in the pool.

发生这种情况是因为容器在池中只有一个bean实例,它被重用于所有调用。如果并行运行客户端,您将看到不同的结果,因为容器将在池中创建更多Bean实例。

#5


3  

The major differences between the two major types of session beans are:

两种主要类型的会话bean之间的主要区别是:

Stateless Beans

无国籍豆

  1. Stateless Session Beans are the ones which have no conversational state with the client which has called its methods. For this reason they can create a pool of objects which can be used to interact with multiple clients.
  2. 无状态会话Bean是与调用其方法的客户端没有会话状态的会话。因此,他们可以创建一个对象池,可用于与多个客户端进行交互。
  3. Performance wise stateless beans are better since they don't have states per client.
  4. 性能明智的无状态bean更好,因为它们没有每个客户端的状态。
  5. They can handle multiple requests from multiple clients in parallel.
  6. 他们可以并行处理来自多个客户端的多个请求。

Stateful Beans

有状态的豆子

  1. Stateful session beans can maintain the conversational state with multiple clients at a time and the task is not shared between the clients.
  2. 有状态会话bean可以一次维护多个客户端的会话状态,并且不在客户端之间共享任务。
  3. After the session is completed the state is not retained.
  4. 会话结束后,不保留状态。
  5. The container can serialize and store the state as a stale state for future use. This is done to save resources of the application server and to support bean failures.
  6. 容器可以将状态序列化并存储为陈旧状态以供将来使用。这样做是为了节省应用程序服务器的资源并支持bean故障。

#6


2  

It has good answers. I would like to add small answer. Stateless Bean should not used to hold any client data. It should be used to "to model actions or processes that can be done in one shot".

它有很好的答案。我想补充一点小问题。无状态Bean不应该用于保存任何客户端数据。它应该用于“模拟可以一次完成的动作或过程”。