EJB3架构介绍与入门指南
立即解锁
发布时间: 2025-08-18 00:14:44 阅读量: 1 订阅数: 4 


EJB 3开发者指南:企业级Java Beans标准实战
# EJB 3 架构介绍与入门指南
## 1. Java EE 架构概述
现代企业应用程序的职责通常分布在多个层次上,常见的是三层架构模型,包括表示层、业务层和数据库层:
- **表示层**:负责呈现用户界面并处理与最终用户的交互。
- **业务层**:负责执行业务逻辑。
- **数据库层**:负责存储业务数据,通常使用关系数据库管理系统。
分层在计算机科学中被广泛用于管理复杂性,每个层都有其独特的用途。
Java 平台企业版(Java EE)技术使用多层架构为企业应用程序提供服务。Java EE 应用程序基于 Java 且支持 Web,这意味着它们可以编写一次并部署在任何支持 Java EE 标准的容器上。应用服务器是容器所在的环境,但在实践中,我们通常不区分应用服务器和容器,这两个术语可以互换使用。Java EE 规范得到了许多商业供应商(如 Sun、IBM、Oracle、BEA Systems)以及开源项目(如 JBoss)的支持。
Java EE 表示层技术包括 Servlet、JSP 页面和 JSF 组件。这些组件为业务应用程序开发,然后部署并运行在 Web 容器中。客户端可以通过浏览器或小程序与 Web 容器进行交互,通信通常使用 HTTP 或 HTTPS 协议。
Enterprise JavaBeans 版本 3(EJB 3)是 Java EE 版本 5(Java EE 5)为业务层提供的技术。在 Java EE 5 中,业务层进一步细分为业务处理层和持久化层。在 EJB 3 中,业务处理组件是会话 bean 和消息驱动 bean,它们为业务应用程序开发并部署在 EJB 容器中运行。持久化层的组件是实体,通过持久化提供程序或持久化引擎将其持久化到数据库层。持久化引擎实现了另一个规范,即 Java 持久化 API(JPA)。EJB 3 和 JPA 都是规范,有许多组织提供它们的实现,这两个规范都可以从 http://www.jcp.org/en/jsr/detail?id=220 下载。
Java EE 5 架构总结如下:
| 层次 | 组件 |
| ---- | ---- |
| 客户端层 | 网页浏览器、小程序、Java 应用程序客户端 |
| 表示层(Web 层) | Servlet、JSP 页面、JSF 组件 |
| 业务层 | 业务逻辑层(会话 bean、消息驱动 bean)、持久化层(实体) |
| 数据库层 | 关系数据库 |
```mermaid
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(客户端层):::process --> B(表示层 - Web 层):::process
B --> C(业务层):::process
C --> D(数据库层):::process
B1(Servlet):::process --> B
B2(JSP 页面):::process --> B
B3(JSF 组件):::process --> B
C1(业务逻辑层):::process --> C
C2(持久化层):::process --> C
C11(会话 bean):::process --> C1
C12(消息驱动 bean):::process --> C1
C21(实体):::process --> C2
D1(关系数据库):::process --> D
```
需要注意的是,三层模型在这里变成了五层模型。客户端/Web 层与业务逻辑/持久化层之间的区别并不总是很明确,因此我们通常将 Java EE 架构简单地称为 n 层或多层架构。Java EE 容器还提供了许多其他服务,如 Web 服务、Java 消息服务(JMS)和资源适配器。
从图中可以看出,我们可以直接从 Java SE 应用程序(如 Swing)访问 EJB,而无需通过 Web 容器。Java 应用程序可以是独立的,也可以从应用程序客户端容器(ACC)运行。ACC 使在 EJB 容器外部的自己的 Java 虚拟机(JVM)中执行的客户端能够访问有限数量的 Java EE 服务。
## 2. EJB 3 架构
EJB 3 架构为开发分布式、面向对象、基于组件的业务应用程序提供了标准。在 EJB 框架中开发的组件是会话 bean 和消息驱动 bean,统称为 EJB。这些通常是相对粗粒度的对象,封装了一个业务流程。它们之所以被称为组件,是因为 EJB 可以组合起来创建一个业务应用程序。此外,如果 EJB 设计良好,它们可以被其他应用程序重用。EJB 是分布式的,因为它们可以驻留在不同的计算机服务器上,并可以由网络上不同系统的远程客户端调用。
### 2.1 会话 bean
会话 bean 必须有一个业务接口,可以是远程接口或本地接口。远程客户端调用会话 bean 的远程接口,而会话 bean 及其客户端可能驻留在同一个 JVM 实例中,在这种情况下,客户端调用会话 bean 的本地接口。
### 2.2 消息驱动 bean
消息驱动 bean 是 JMS 消息的异步接收者。客户端(可以是 Java 应用程序或 Java EE 组件,如会话 bean)将 JMS 消息发送到消息队列或主题。消息队列或主题可以由 Java EE 容器管理,也可以由专用的 JMS 服务器管理。
EJB 部署并运行在一个容器中,该容器旨在使应用程序具有可扩展性、支持多用户并保证线程安全。EJB 容器还提供了企业级业务应用程序可能需要的许多服务。
与会话 bean 和消息驱动 bean 不同,实体是相对细粒度的对象,具有较长的生命周期并且需要持久化。在 EJB 3 之前,实体 bean 扮演实体的角色,并被定义为可远程访问的组件,就像会话 bean 和消息驱动 bean 一样。在 EJB 3 中,实体是 Java 对象,因此可以利用面向对象的特性,如继承和多态,而实体 bean 则无法做到这一点。在 EJB 3 中,实体由实现 JPA 规范的持久化提供程序或持久化引擎进行持久化。这个持久化引擎可以在 EJB 容器内运行,也可以在不需要其他 EJB 服务的业务应用程序的容器外运行。
严格来说,EJB 作为可远程访问的组件,仅包括会话 bean 和消息驱动 bean,不包括实体。但在一般情况下,除非特定上下文需要区分,否则我们提到 EJB 时通常会包括实体。当我们提到 EJB 组件时,指的是会话 bean 和消息驱动 bean,而不包括实体。由于 EJB 基于 Java,因此可以编写一次并部署在任何支持 EJB 标准的应用服务器上。
### 2.3 EJB 容器服务
EJB 容器提供了大量的服务,以下是一些主要的服务:
- **并发支持**:EJB 容器支持并发,所有 EJB 组件都是线程安全的。
- **实例池化**:EJB 容器为 EJB 组件实例提供池化,这有助于提高 EJB 架构的可扩展性。
- **命名服务**:EJB 容器提供 Java 命名和目录接口(JNDI),用于访问 EJB 或任何其他容器管理的资源,如 JMS 队列连接。在 EJB 3 中,还提供了一种基于注解的更简单的依赖注入机制,在很多情况下可以替代 JNDI。
- **远程方法调用**:所有 EJB 3 容器都支持 Java RMI - IIOP(通过 Internet Inter - Orb 协议运行的远程方法调用),这使得客户端可以远程访问会话 bean。客户端不需要知道所调用的 EJB 是远程的还是本地的(即是否驻留在同一个 JVM 中),这种特性称为位置透明性。
- **事务管理**:业务系统通常具有事务性,EJB 提供容器管理的事务服务。
- **消息支持**:EJB 通过提供基于 JMS 的消息驱动 bean 支持消息传递。
- **调度功能**:EJB 提供基本的调度功能,即定时器服务。
- **拦截器服务**:EJB 3 的一个新特性是拦截器服务,它允许将 EJB 组件的通用、次要方面与任何业务逻辑分离,该概念基于面向方面编程(AOP)。
- **Web 服务转换**:EJB 允许将无状态会话 bean 转换为 Web 服务。
- **安全标准**:EJB 为安全的认证和授权方面提供标准。认证用于验证用户的身份,授权用于控制用户对应用程序或应用程序部分的访问。
- **实体持久化**:大多数业务应用程序需要实体持久化服务,在 EJB 3 中,该服务由容器委托给 Java 持久化 API(JPA)持久化引擎。
### 2.4 JPA 持久化引擎
许多应用程序不需要 EJB 容器提供的服务,但仍然需要持久化服务。因此,JPA 作为一个单独的规范发布,运行在 EJB 容器外的应用程序也可以使用 JPA 服务。JPA 的主要服务包括:
- **实体管理器**:提供持久化、事务管理和管理实体生命周期的服务。
- **对象/关系映射**:提供对象/关系元数据注解,用于将实体映射到关系数据库表。
- **Java 持久化查询语言(JPQL)**:用于检索持久化的实体。
虽然 JPA 规范是最近发布的,但它借鉴了与 Hibernate 和 Oracle Toplink 等产品相关的对象/关系映射技术。这些产品已经存在多年,例如 Toplink 已经有十多年的历史。JPA 规范尤其大量借鉴了这两个产品。此外,Toplink 和 Hibernate 是许多 EJB 3 容器的实际默认持久化引擎。例如,Sun 的 GlassFish 容器和 Oracle Application Server 11g 都使用 Toplink 作为嵌入式持久化引擎,而 JBoss EJB 3 容器使用 Hibernate 作为嵌入式持久化引擎。不过,这些都是可插拔的默认设置,例如也可以在 GlassFish 中使用 Hibernate。
### 2.5 EJB 3 与早期版本的比较
EJB 3 引入的主要特性可以总结如下:
- **简化的持久化 API**:与 EJB 2.x 相比,EJB 3 在持久化处理上有了很大改进。在 EJB 3 之前,实体 bean 与关系表之间的对象/关系映射非常有限,并且不支持继承和多态。而 EJB 3 中的实体是真正的 Java 对象。
- **元数据注解**:元数据注解首次在 Java SE 5 中引入,因此开发 EJB 3 应用程序时必须使用该版本或更高版本的 Java。元数据注解可以作为 XML 部署描述符的替代,用于配置 EJB 组件和指定实体的对象/关系映射,但在这两种情况下也可以使用部署描述符。
- **改进的查询语言**:早期版本的 EJB 查询语言(EJB QL)相对有限,而 JPA 的 JPQL 提供了许多增强功能,如投影、GROUP BY 和 HAVING 子句、连接、子查询、动态查询、带参数的查询以及批量更新和删除操作。
- **默认值的使用**:EJB 3 广泛使用默认值,大多数元数据注解不需要指定元素或参数,默认值通常是常见的、预期的行为。只有在需要配置特殊行为时才需要指定注解元素。
- **依赖注入**:依赖注入首次在 Spring 框架中出现,在 EJB 3 中作为查找容器管理资源的替代方法引入,可替代 JNDI。
- **会话 bean 的简化**:在 EJB 3 中,不再需要指定组件和主接口,并且会话 bean 类不再需要实现许多回调接口,除非应用程序确实需要这些接口。只有在需要时,会话 bean 才会实现这些生命周期回调方法。
## 3. 入门指南
### 3.1 安装 GlassFish
在安装 GlassFish 之前,请确保您的工作站上安装了 Java 开发工具包(JDK)的版本 5 或更高版本,您可以从 http://java.sun.com/javase/downloads/index.jsp 下载。这里我们使用的是 JDK 5.0 Update 12。
安装步骤如下:
1. 设置环境变量 `JAVA_HOME` 指向 JDK 的安装目录,并将 `%JAVA_HOME%\bin` 添加到 `PATH` 环境变量中。具体操作是:点击开始菜单中的“控制面板”,然后双击“系统”图标,选择“系统属性”框中的“高级”选项卡,最后点击“环境变量”按钮。
2. 从 https://glassfish.dev.java.net// 下载版本等于或高于 V2b41d 的 GlassFish 到您想要安装的目录。这里使用的下载文件是 `glassfish - installer - v2 - b41d.jar`。在下载的 jar 文件所在的目录中,运行以下命令:
```bash
java -Xmx256m -jar glassfish-installer-v2-b41d.jar
```
这将解压文件并创建 `glassfish` 子目录。
3. 设置环境变量 `GLASSFISH_HOME` 指向 GlassFish 的安装目录,并将 `%GLASSFISH_HOME%\bin` 添加到 `PATH` 环境变量中。
4. 设置环境变量 `ANT_HOME` 指向 Ant 的安装目录。GlassFish 附带了 Ant 构建工具,安装的 Ant 目录将是 `glassfish\lib\ant`。如果您已经安装了版本等于或高于 1.6.5 的 Ant,请相应地设置 `ANT_HOME`。然后将 `%ANT_HOME%\bin` 添加到 `PATH` 环境变量中。
5. 切换到 `glassfish` 目录,通过运行 Ant 安装脚本完成安装:
```bash
ant -f setup.xml
```
安装过程可能会因为与现有软件的端口冲突而失败。如果出现这种情况,您需要编辑 `setup.xml` 文件。在文件中,您会看到以下设置默认属性的片段:
```xml
<property name="domain.name" value="domain1"/>
<property name="instance.name" value="server"/>
<property name="admin.user" value="admin"/>
<property name="admin.password" value="adminadmin"/>
<property name="admin.port" value="4848"/>
<property name="instance.port" value="8080"/>
<property name="orb.port" value="3700"/>
<property name="imq.port" value="7676"/>
<property name="https.port" value="8181"/>
<property name="glassfish.license" value="LICENSE.txt"/>
```
修改冲突端口的值,然后再次运行安装脚本。
### 3.2 测试安装
使用以下命令启动 GlassFish:
```bash
asadmin start-domain domain1
```
如果启动成功,您应该会看到一些消息,其中包括管理控制台的 URL 和 Web 应用程序的 URL。在浏览器中输入 http://localhost:8080,如果 GlassFish 正确启动,您应该会看到相应的页面。
### 3.3 访问管理控制台
在浏览器中输入 http://localhost:4848,默认用户名是 `admin`,默认密码是 `adminadmin`。输入这些信息后,您将进入管理控制台页面。管理控制台可用于许多任务,如创建和配置域、监控性能和部署应用程序。另一种部署应用程序的方法是使用命令行的 `asadmin` 工具。
### 3.4 关闭 GlassFish
使用以下命令停止 GlassFish:
```bash
asadmin stop-domain domain1
```
### 3.5 下载示例源代码
示例的源代码可以在相关网站上以 zip 文件的形式下载。下载文件并将其解压到您选择的驱动器和目录中。示例假设源代码已下载到 `C:\` 目录,子目录对应于各个章节,如 `C:\EJB3Chapter02`、`C:\EJB3Chapter03` 等。在运行任何脚本之前,请先查看 `readme` 文件。
## 4. 会话 bean 概述
会话 bean 是一种 EJB 技术,用于封装业务流程或工作流。以下是关于会话 bean 的一些基本信息:
### 4.1 会话 bean 的用途
在面向对象分析和设计中,控制类封装了用例的业务逻辑,会话 bean 用于实现这样的控制类。例如,检查信用卡详细信息、转账和预订图书等操作都可能是会话 bean 的候选。会话 bean 是临时的,生命周期相对较短,它们不是持久化的,不会存储在数据库或其他永久文件系统中。但会话 bean 可以创建和更新持久化的实体。
### 4.2 客户端与会话 bean 的交互
客户端通过调用会话 bean 中定义的一个或多个方法来与会话 bean 进行交互,这一系列的方法调用称为一个会话,这也是会话 bean 名称的由来。客户端可以是 Web 层客户端(如 Servlet 或 JSP 页面),也可以是独立的 Java 应用程序。
### 4.3 会话 bean 的组成
与 EJB 2.x 一样,EJB 3 会话 bean 也是一种组件技术。在 EJB 3 中,会话 bean 组件由一个 bean 接口和一个 bean 类组成。bean 接口提供所有 bean 方法的定义,bean 类提供方法的实现。与 EJB 2.x 不同的是,我们不再需要生成主接口。
会话 bean 主要分为无状态会话 bean 和有状态会话 bean,后续我们将详细介绍它们的特点和使用方法。同时,我们还会涉及到注解的使用、会话 bean 的打包和部署以及如何从应用程序客户端容器运行会话 bean 客户端等内容。
```mermaid
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(客户端):::process --> B(会话 bean):::process
B --> C(实体):::process
B1(无状态会话 bean):::process --> B
B2(有状态会话 bean):::process --> B
A1(Web 层客户端):::process --> A
A2(独立 Java 应用程序):::process --> A
```
总之,EJB 3 架构为企业级应用程序的开发提供了强大而灵活的支持,通过合理使用 EJB 3 的各种组件和服务,可以构建出高效、可扩展和安全的业务应用程序。希望本文能帮助您初步了解 EJB 3 架构,并顺利开始使用 GlassFish 容器进行开发。
## 5. 无状态会话 bean
### 5.1 无状态会话 bean 的特点
无状态会话 bean 不维护特定客户端的会话状态。这意味着在不同的方法调用之间,它不会保留任何与特定客户端相关的数据。每次客户端调用无状态会话 bean 的方法时,该 bean 都会以相同的初始状态响应。例如,一个用于计算两个数之和的无状态会话 bean,无论何时被调用,它都会根据传入的参数进行计算,而不会受到之前调用的影响。
### 5.2 无状态会话 bean 的使用场景
无状态会话 bean 适用于那些不需要维护会话状态的业务逻辑,如执行简单的数学计算、数据查询、文件操作等。以下是一个简单的无状态会话 bean 示例:
```java
import javax.ejb.Stateless;
@Stateless
public class CalculatorBean {
public int add(int a, int b) {
return a + b;
}
}
```
在这个示例中,`CalculatorBean` 是一个无状态会话 bean,它提供了一个 `add` 方法用于计算两个整数的和。
### 5.3 无状态会话 bean 的生命周期
无状态会话 bean 的生命周期相对简单。容器会维护一个无状态会话 bean 的实例池,当客户端请求时,容器会从池中取出一个实例来处理请求。处理完成后,该实例会被返回到池中,等待下一次请求。这种池化机制提高了系统的性能和可扩展性。
```mermaid
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(客户端请求):::process --> B(从实例池获取实例):::process
B --> C(处理请求):::process
C --> D(返回结果):::process
D --> E(实例返回池):::process
```
## 6. 有状态会话 bean
### 6.1 有状态会话 bean 的特点
与无状态会话 bean 不同,有状态会话 bean 会维护特定客户端的会话状态。在客户端与有状态会话 bean 进行交互的过程中,bean 会保留客户端的相关数据,直到会话结束。例如,一个用于购物车管理的有状态会话 bean,会记录用户添加到购物车中的商品信息,直到用户完成购物或取消购物。
### 6.2 有状态会话 bean 的使用场景
有状态会话 bean 适用于那些需要维护会话状态的业务逻辑,如在线购物、用户登录、游戏等。以下是一个简单的有状态会话 bean 示例:
```java
import javax.ejb.Stateful;
import java.util.ArrayList;
import java.util.List;
@Stateful
public class ShoppingCartBean {
private List<String> items = new ArrayList<>();
public void addItem(String item) {
items.add(item);
}
public List<String> getItems() {
return items;
}
}
```
在这个示例中,`ShoppingCartBean` 是一个有状态会话 bean,它提供了一个 `addItem` 方法用于向购物车中添加商品,以及一个 `getItems` 方法用于获取购物车中的商品列表。
### 6.3 有状态会话 bean 的生命周期
有状态会话 bean 的生命周期与客户端会话相关。当客户端创建一个有状态会话 bean 时,容器会为该客户端分配一个唯一的实例。在会话期间,该实例会一直为该客户端服务,直到会话结束。会话结束的原因可能是客户端显式关闭会话、会话超时或容器关闭等。
```mermaid
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(客户端创建会话):::process --> B(分配唯一实例):::process
B --> C(处理客户端请求):::process
C --> D{会话是否结束?}:::process
D -- 否 --> C
D -- 是 --> E(销毁实例):::process
```
## 7. 注解的使用
在 EJB 3 中,注解是一种非常重要的特性,它可以简化 EJB 组件的开发和配置。以下是一些常用的注解及其用途:
| 注解 | 用途 |
| ---- | ---- |
| `@Stateless` | 用于标记无状态会话 bean |
| `@Stateful` | 用于标记有状态会话 bean |
| `@MessageDriven` | 用于标记消息驱动 bean |
| `@Entity` | 用于标记实体类 |
| `@PersistenceContext` | 用于注入持久化上下文 |
| `@EJB` | 用于注入 EJB 组件 |
例如,在前面的无状态会话 bean 示例中,我们使用了 `@Stateless` 注解来标记 `CalculatorBean` 为无状态会话 bean。注解的使用可以替代传统的 XML 部署描述符,使代码更加简洁和易于维护。
## 8. 会话 bean 的打包和部署
### 8.1 打包会话 bean
会话 bean 通常需要打包成一个可部署的单元,如 JAR 文件。打包过程可以使用 Ant、Maven 等构建工具来完成。以下是一个简单的 Ant 构建脚本示例:
```xml
<project name="EJBProject" default="deploy" basedir=".">
<property name="src.dir" value="src"/>
<property name="build.dir" value="build"/>
<property name="dist.dir" value="dist"/>
<property name="ejb.jar" value="${dist.dir}/ejb.jar"/>
<target name="init">
<mkdir dir="${build.dir}"/>
<mkdir dir="${dist.dir}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src.dir}" destdir="${build.dir}"/>
</target>
<target name="jar" depends="compile">
<jar destfile="${ejb.jar}" basedir="${build.dir}"/>
</target>
<target name="deploy" depends="jar">
<!-- 部署到 GlassFish 容器 -->
<exec executable="asadmin">
<arg value="deploy"/>
<arg value="${ejb.jar}"/>
</exec>
</target>
</project>
```
这个 Ant 脚本定义了四个目标:`init` 用于创建构建和分发目录,`compile` 用于编译源代码,`jar` 用于将编译后的类打包成 JAR 文件,`deploy` 用于将 JAR 文件部署到 GlassFish 容器中。
### 8.2 部署会话 bean
部署会话 bean 可以使用 GlassFish 管理控制台或命令行工具 `asadmin`。使用 `asadmin` 工具部署的命令如下:
```bash
asadmin deploy /path/to/ejb.jar
```
部署成功后,会话 bean 就可以被客户端调用了。
## 9. 从应用程序客户端容器运行会话 bean 客户端
应用程序客户端容器(ACC)允许客户端在独立的 Java 虚拟机中运行,并访问 EJB 组件。以下是从应用程序客户端容器运行会话 bean 客户端的步骤:
1. **创建客户端代码**:编写一个 Java 客户端程序,使用 `@EJB` 注解注入会话 bean 并调用其方法。
```java
import javax.ejb.EJB;
import javax.naming.InitialContext;
public class Client {
@EJB
private static CalculatorBean calculator;
public static void main(String[] args) {
try {
InitialContext ctx = new InitialContext();
calculator = (CalculatorBean) ctx.lookup("java:global/ejb/CalculatorBean");
int result = calculator.add(2, 3);
System.out.println("Result: " + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
2. **配置客户端环境**:确保客户端环境中包含必要的类库,如 EJB 容器的客户端库和 JNDI 相关的类库。
3. **运行客户端程序**:使用 `java` 命令运行客户端程序。
```bash
java -cp /path/to/client.jar:/path/to/ejb-client-lib.jar Client
```
通过以上步骤,你可以从应用程序客户端容器运行会话 bean 客户端,并与 EJB 组件进行交互。
综上所述,EJB 3 架构中的会话 bean 为企业级应用程序的开发提供了强大的支持。无状态会话 bean 和有状态会话 bean 分别适用于不同的业务场景,通过合理使用注解、打包和部署技术,以及从应用程序客户端容器运行客户端程序,我们可以构建出高效、可扩展和易于维护的企业级应用程序。
0
0
复制全文
相关推荐










