Contents

Java EE会话bean

1. 简介

企业会话 Bean 可以大致分为:

  1. 无状态会话 Bean
  2. 有状态会话 Bean

在这篇快速文章中,我们将讨论这两种主要类型的会话 bean。

2. 设置

要使用 Enterprise Beans 3.2 **,**请确保将最新版本添加到pom.xml文件的依赖项部分:

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>

最新的依赖可以在Maven Repository 中找到。这种依赖关系确保所有 Java EE 7 API 在编译期间都可用。提供的范围确保一旦部署;依赖项将由部署它的容器提供。

3. 无状态 Bean

无状态会话 bean 是一种企业 bean,通常用于执行独立操作。它没有任何关联的客户端状态,但它可以保留其实例状态。

让我们看一个示例来演示无状态 bean 的工作原理。

3.1. 创建无状态 Bean

首先,让我们创建StatelessEJB bean。我们使用*@Stateless*注解将 bean 标记为无状态:

@Stateless
public class StatelessEJB {
    public String name;
}

然后我们创建上述无状态 bean 的第一个客户端,称为EJBClient1

public class EJBClient1 {
    @EJB
    public StatelessEJB statelessEJB;
}

然后我们声明另一个客户端,名为*EJBClient2,*它访问同一个无状态 bean:

public class EJBClient2 {
    @EJB
    public StatelessEJB statelessEJB;
}

3.2. 测试无状态 Bean

为了测试 EJB 的无状态性,我们可以通过以下方式使用我们上面声明的两个客户端:

@RunWith(Arquillian.class)
public class StatelessEJBTest {
    @Inject
    private EJBClient1 ejbClient1;
    @Inject
    private EJBClient2 ejbClient2;
    @Test
    public void givenOneStatelessBean_whenStateIsSetInOneBean
      _secondBeanShouldHaveSameState() {
        ejbClient1.statelessEJB.name = "Client 1";
        assertEquals("Client 1", ejbClient1.statelessEJB.name);
        assertEquals("Client 1", ejbClient2.statelessEJB.name);
    }
    @Test
    public void givenOneStatelessBean_whenStateIsSetInBothBeans
      _secondBeanShouldHaveSecondBeanState() {
        ejbClient1.statelessEJB.name = "Client 1";
        ejbClient2.statelessEJB.name = "Client 2";
        assertEquals("Client 2", ejbClient2.statelessEJB.name);
    }
    // Arquillian setup code removed for brevity
}

我们首先将两个 EBJ 客户端注入到单元测试中。

然后,在第一个测试方法中,我们将注入EJBClient1的 EJB 中的name变量设置为值Client 1。现在,当我们比较两个客户端中name变量的值时,我们应该看到该值相等. 这表明状态没有保存在无状态 bean中。

让我们以不同的方式证明这是真的。在第二种测试方法中,我们看到一旦我们在第二个客户端中设置了name变量,它就会“覆盖”通过ejbClient1赋予它的任何值。

4. 有状态的 Bean

有状态会话 bean 在事务内部和事务之间维护状态。这就是为什么每个有状态会话 bean 都与特定客户端相关联的原因。容器可以在管理有状态会话 bean 的实例池时自动保存和检索 bean 的状态。

4.1. 创建有状态 Bean

有状态会话 bean 使用*@Stateful*注释进行标记。有状态bean的代码如下:

@Stateful
public class StatefulEJB {
    public String name;
}

我们有状态 bean 的第一个本地客户端编写如下:

public class EJBClient1 {
    @EJB
    public StatefulEJB statefulEJB;
}

就像EJBClient1一样,还创建了第二个名为EJBClient2的客户端:

public class EJBClient2 {
    @EJB
    public StatefulEJB statefulEJB;
}

4.2. 测试有状态 Bean

有状态 bean 的功能在EJBStatefulBeanTest单元测试中通过以下方式进行测试:

@RunWith(Arquillian.class)
public class StatefulEJBTest {
    @Inject
    private EJBClient1 ejbClient1;
    @Inject
    private EJBClient2 ejbClient2;
    @Test
    public void givenOneStatefulBean_whenTwoClientsSetValueOnBean
      _thenClientStateIsMaintained() {
        ejbClient1.statefulEJB.name = "Client 1";
        ejbClient2.statefulEJB.name = "Client 2";
        assertNotEquals(ejbClient1.statefulEJB.name, ejbClient2.statefulEJB.name);
        assertEquals("Client 1", ejbClient1.statefulEJB.name);
        assertEquals("Client 2", ejbClient2.statefulEJB.name);
    }
    // Arquillian setup code removed for brevity
}

和之前一样,将两个 EJB 客户端注入到单元测试中。在测试方法中,我们可以看到name变量的值是通过ejbClient1客户端设置的,并且即使通过ejbClient2设置的name值不同,也会保持不变。这表明 EJB 的状态得到了维护

5. 无状态与有状态会话 Bean

现在让我们看看这两种类型的会话 bean 之间的主要区别。

5.1. 无状态 Bean

  • 无状态会话 bean 不与客户端保持任何状态。因此,它们可用于创建与多个客户端交互的对象池
  • 由于无状态 bean 没有每个客户端的任何状态,因此它们在性能方面更好
  • 他们可以并行处理来自多个客户端的多个请求,并且
  • 可用于从数据库中检索对象

5.2. 有状态的 Bean

  • 有状态会话 bean 可以与多个客户端保持状态,并且任务不在客户端之间共享
  • 该状态在会话期间持续。session销毁后,不保留状态
  • 容器可以将状态序列化并存储为陈旧状态以供将来使用。这样做是为了节省应用程序服务器资源并支持 bean 故障并且是钝化
  • 可用于解决生产者-消费者类型问题