在本文中,我们将了解 EJB——Enterprise JavaBeans。该技术是 Java EE 规范的一部分。我们将讨论以下问题:
- 什么是 EJB;
- EJB 的历史是什么?
- 有哪些类型的 EJB?
EJB 简史
早在 1996 年,当本文作者 5 岁的时候,Java 就已经在开发者中流行起来。其原因是友好的API、自动垃圾收集等。Java被广泛应用于负责后端的系统中。然而,尽管该语言有很多乐趣,但当时的程序员需要 JDK 中尚未实现的某些功能。这些需求是:- 确保数据持久性;
- 交易完整性
- 竞争性访问数据(多线程控制);
- 很可能还有别的东西。
什么是EJB
从某种意义上说,EJB 是一个集体术语,根据上下文,它可以表示一般的 Enterprise JavaBeans 技术本身,也可以表示属于 EJB 技术一部分的某些特定 Enterprise JavaBean 软件组件 (bean)。维基百科上给出了 EJB 作为一种技术的定义:Enterprise JavaBeans(也经常用作缩写 EJB)是一种用于编写和支持包含业务逻辑的服务器组件的技术规范。它是 Java EE 的一部分。当业务逻辑至少需要以下服务之一(通常是所有服务)时,通常使用此技术:- 支持数据持久性:即使停止程序后数据也应该是安全的。最常使用数据库来实现;
- 支持分布式事务;
- 支持并行数据修改和多线程;
- 活动支持;
- 命名和目录支持(JNDI);
- 数据访问的安全性和限制;
- 支持在应用服务器上自动安装;
- 远程访问。
EJB类型
我们来总结一下。EJB 是一个带有特殊注释之一的常规 Java 类。这样的类称为 Bean。根据类标记的注释,它将代表一种或另一种类型的 EJB(bean)。豆子主要分为三种类型:- Message Driven Beans(消息驱动bean);
- Entity Beans——在JPA(Java Persistence API)规范中定义,用于存储数据;
- 会话 Bean。
- 无状态(无状态);
- 有状态(支持当前会话状态);
- 单例(整个应用程序的一个对象;从 EJB 3.1 开始)。
会话Bean
会话 Bean,或称会话 Bean,是一种特定类型的 Bean。它们封装了客户端可以通过调用 bean 的方法以编程方式调用的业务逻辑。方法调用可以执行以下操作:- 本地,通过与会话 bean 相同的 JVM 中的另一个类;
- 使用 Java RMI(远程方法调用)技术,通过网络从另一个 JVM 进行远程操作。
@Stateless
。下面我们举个例子:
import javax.ejb.Stateless;
@Stateless
public class StatelessEjbExample {
public String sayHi() {
return "Hi, I'm Stateless EJB!";
}
}
支持当前会话状态(有状态)的会话 bean保留有关同一客户端调用之间的状态信息,并根据客户端的显式请求终止其存在。这是因为有状态 Bean 对于每个客户端来说都是唯一的。这种类型的 Bean 可以负责的任务的一个示例是使在线商店中的购物车为每个用户保持最新。这些bean 的生命周期由EJB 容器管理。当客户端退出时,这些 Bean 也会被销毁。这样的豆子也很容易创建。这是一个用注释标记的 Java 类Stateful
。下面的例子:
import javax.ejb.Stateful;
@Stateful
public class StatefulEjbExample {
public String sayHi() {
return "Hi, I,m Stateful EJB";
}
}
单例会话 bean在应用程序的生命周期内启动一次,并在应用程序的整个生命周期中存在。此类 Bean 专为必须在所有客户端之间共享一种状态的情况而设计。与无状态 Bean 一样,在独立 Bean 中,开发人员需要确保 Bean 具有线程安全的环境。让我们举一个 Singleton bean 的例子,它和上面讨论的对应的 bean 一样容易创建。很容易猜到这是一个带有注释的Java类@Singleton
。但是,在这种情况下您需要小心。有两个注释,语法相同,但用途不同并且位于不同的包中:
- javax.ejb.Singleton
- javax.inject.Singleton
javax.ejb
. 下面的例子:
import javax.ejb.Singleton;
@Singleton
public class SingletonEjbExample {
public String sayHi() {
return "Hi, I'm Singleton EJB!";
}
}
消息驱动 Bean
消息驱动 Bean(或 MDB)或消息驱动 Bean 实现一些业务逻辑,如会话 Bean。但与它的亲戚不同的是,MDB 有一个重要的区别。客户端从不直接调用 MDB 方法。此类 Bean 通常充当 JMS(Java 消息服务)消息的侦听器,并用于组织系统各部分之间的异步消息交换。此类消息的一个示例是从自动化零售系统向供应管理系统传送库存的请求。下面是 MDB bean 的示例。与会话 bean 不同,它的创建更有趣一些:import javax.annotation.Resource;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
@MessageDriven(mappedName = "jms/TestQueue")
public class MessageDrivenEjbExample implements MessageListener {
@Resource
private MessageDrivenContext messageDrivenContext;
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage msg = (TextMessage) message;
msg.getText();
}
} catch (JMSException e) {
messageDrivenContext.setRollbackOnly();
}
}
}
该注释MessageDriven
使我们的 MDB 类成为一个 bean。在注释内部,使用 JNDI(在此处阅读有关 JNDI的信息)确定了 JMS 发行版的名称,我们的类将成为该发行版的侦听器。此外,我们的类还实现了该接口MessageListener
及其方法onMessage
。当一些消息从队列/分发到达且其名称在注释中定义时,将调用此方法MessageDriven
。
实体bean
EJB 技术的一部分是 JPA 规范。JPA(即 Java Persistence API)是一种规范,它提供 Java 对象(实体 bean)的对象关系映射 (ORM),并提供用于存储、检索和管理此类对象的 API。JPA 允许您将数据库中的数据表示为 Java 对象,以及将 Java 对象保存为数据库中的记录。并不是每个类都可以充当这样的对象,但实体 bean 除外。Entity Bean 是一个 Java 类,表示数据库中的表。显示(映射)是通过使用特殊注释来实现的。在它们的帮助下,可以将 Java 类与数据库中的表进行比较,以及将 Java 类的字段与数据库表的字段进行比较。下面是一个实体 bean 的示例,代码中带有注释:@Entity // Делает данный класс Entity бином
@Table(name = "employee") // "Связывает" данный класс с таблицей employee в БД
public class Employee implements Serializable {
@Id // Говорит о том, что поле ниже является первичным ключом
@GeneratedValue(strategy = GenerationType.AUTO) // Определяет тип генерации значений первичного ключа
private int id;
@Column(name="name") // "Связывает" поле ниже с полем name в таблице employee в БД
private String name;
@Column (name="age") // "Связывает" поле ниже с полем age в таблице employee в БД
private int age;
// getters and setters...
}
值得注意的是,这种类型的 bean 仅在研究 JPA 规范的背景下才有意义。
编写应用程序:EJB HelloWorld
在本节中,我们将编写一个小型 Java EE HelloWorld 应用程序,并将其部署在 GlassFish 服务器上。在阅读本文之前,强烈建议您阅读有关设置本地环境的文章。-
在 IntelliJ IDEA 中创建一个新的 Maven 项目。
文件 -> 新建 -> 项目...
-
点击下一步。
-
填写Maven项目参数:
-
单击“完成”
-
该项目已创建并具有以下结构:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javarush.lectures</groupId>
<artifactId>ejb_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
</dependencies>
</project>
接下来,您可以继续处理 Java 代码。我们的应用程序将是最简单的。我们将有 1 个 servlet 和 1 个 EJB。这将是一个无状态会话 bean。在 EJB 内部,我们将仅定义 1 个返回字符串“Hello World”的方法。首先,让我们创建一个包com.javarush.lectures
。然后,在包内com.javarush.lectures
,我们将创建我们的 bean - DemoEJB。bean代码如下:
import javax.ejb.Stateless;
@Stateless
public class DemoEJB {
public String helloWorld() {
return "Hello world!";
}
}
正如前面所说,一切都很简单。我们的下一步是创建一个 servlet,它将传递来自 EJB 的值作为对 HTTP 请求的响应。值得注意的是,servlet 不是本文的主题,但您仍然需要使用它们来演示 EJB。为此,我们DemoServlet
在与 EJB 相同的包中创建一个新的 servlet。其代码如下:
@WebServlet("/helloWorld")
public class DemoServlet extends HttpServlet {
@EJB
private DemoEJB ejb;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write(ejb.helloWorld());
}
}
以下是对代码的一些简短评论。Abstract @WebServlet("/helloWorld")
- 将我们的类定义为 servlet,它将处理对端点的 HTTP 请求/helloWorld
。我们班有一个场地—— DemoEJB ejb
. 这是我们之前定义的 bean。类字段上的注释 —@EJB
执行依赖项注入 (DI)。那些。需要时,ejb 变量会自动用新实例进行初始化。我们的类是 HttpServlet 的后代,并重写超类方法之一 - doGet
。此方法处理 HTTP GET 请求并采用两个参数 -HttpServletRequest
和HttpServletResponse
。HttpServletRequest
用于获取有关传入 HTTP 请求的信息。HttpServletResponse
需要生成对请求的响应。在方法内部,我们使用PrintWriter
.response 对象从响应对象 ( ) 获取对象。接下来,我们可以使用 向结果对象写入一些值。事实上,我们通过将从我们定义的 EJB 获得的值写入 -a 对象来使用它(该值是字符串“Hello World!”)。发送 HTTP 请求的客户端将收到此值作为对其请求的响应。下一步是在 GlassFish Java EE 服务器上启动应用程序。为此,我们将创建一个新配置,如有关设置本地环境的文章中所述。下面是当前项目完成配置的屏幕截图。确保在开始之前安装了 GlassFish 服务器: 创建启动配置后,使用Run -> Run 'ejb_demo'菜单或使用Shift+F10热键启动应用程序。启动后,您可以看到它的日志: 以及打开的浏览器: 所有这些都表明应用程序按预期工作。 HttpServletResponse
getWriter()
write
PrintWriter
结论
在本文中,我们了解了 EJB——Enterprise JavaBeans。我们考虑了以下问题:- 什么是EJB?
- EJB历史
- 不同类型的 EJB
- Message Driven Beans(消息驱动bean);
- Entity Beans - 在JPA(Java Persistence API)实体规范中定义并用于存储数据;
- 会话 Bean:
- 无状态(无状态)
- 有状态(支持当前会话状态)
- 单例(整个应用程序的一个对象;从 EJB 3.1 开始)
GO TO FULL VERSION