17、企业级服务--EJB

17、企业级服务--EJB

Enterprise JavaBeans (EJB)

关键点总结:

理解EJB分类:明确Stateless、Stateful和Entity Bean的用途。生命周期管理:了解不同Bean的生命周期,合理设计业务逻辑。注解配置:熟练使用EJB和JPA注解,简化配置和管理。实践经验:通过实际项目,掌握EJB的开发流程和调试技巧。

一、Enterprise JavaBeans (EJB) 的定义

Enterprise JavaBeans(EJB)是Java EE(Enterprise Edition)的一部分,主要用于封装企业级应用中的业务逻辑。EJB组件由容器管理,提供了事务管理、安全性、资源管理等功能,简化了企业级应用的开发。EJB使得开发者能够专注于业务逻辑的实现,而无需关心底层的复杂性,如事务管理和资源访问。

二、EJB 的分类

EJB主要分为三种类型,每种类型适用于不同的应用场景:

无状态会话Bean (Stateless Session Bean)

定义:无状态会话Bean不维护客户端的状态,每次客户端请求都会创建一个新的Bean实例,或重用已有的实例。特点:

适用于不需要维护会话状态的业务逻辑。容器管理Bean的生命周期,开发者无需关心创建和销毁。由于无状态,Bean实例可以被多个客户端共享,提高了资源利用率。

使用场景:适用于执行一次性操作,如计算、数据处理等,不涉及用户会话的维护。

有状态会话Bean (Stateful Session Bean)

定义:有状态会话Bean维护客户端的状态,在整个会话期间保留Bean的状态。特点:

适用于需要维护会话状态的业务逻辑。每个客户端都有一个专用的Bean实例,维护该客户端的状态。容器负责Bean的生命周期管理,但开发者需要实现特定的生命周期方法。

使用场景:适用于需要跟踪用户会话的应用,如购物车、在线测试等。

实体Bean (Entity Bean)

定义:实体Bean用于与数据库交互,管理持久化数据。它表示数据库中的实体,通常与数据库表对应。特点:

通过持久化提供与数据库的交互。支持事务管理,确保数据一致性。提供了基于对象的数据访问,简化了数据库操作。

使用场景:适用于需要与数据库交互、管理实体数据的应用,如ORM(对象关系映射)、CRUD(增删改查)操作等。注意:在EJB 3.0及以后版本中,实体Bean已被Java Persistence API (JPA)取代,JPA提供了更简便和高效的持久化解决方案。

三、EJB 的优势

事务管理:EJB容器提供了自动的事务管理,确保数据库操作的原子性、一致性、隔离性和持久性(ACID)。开发者无需手动管理事务,简化了代码实现。安全性:EJB容器提供了基于角色的访问控制(RBAC),可以通过配置安全角色和权限,保护业务逻辑不被未授权访问。开发者可以声明式地配置安全性,减少代码中的安全逻辑。资源管理:EJB容器能够管理资源如数据库连接池、JMS队列等,确保资源的高效利用和正确释放,避免资源泄漏。并发管理:容器负责管理并发访问,确保Bean实例在多线程环境下的线程安全,开发者无需关心同步和锁机制。可扩展性和可维护性:EJB的组件化特性使得应用更容易扩展和维护。通过模块化设计,各个业务逻辑单元可以独立开发和测试,提高了系统的可维护性。跨平台支持:EJB规范是跨平台的,应用可以在不同的EJB容器中运行,提高了应用的可移植性。

四、EJB 的生命周期

不同类型的EJB有不同的生命周期:

无状态会话Bean (Stateless Session Bean):

创建:客户端请求时,容器创建Bean实例。调用业务方法:客户端调用Bean的业务方法执行操作。销毁:请求完成后,容器回收Bean实例,或将其返回到池中供下次请求使用。

有状态会话Bean (Stateful Session Bean):

创建:客户端请求时,容器创建Bean实例,并与客户端会话关联。方法调用:在整个会话过程中,客户端调用Bean的业务方法,Bean维护客户端的状态。销毁:会话结束或超时后,容器销毁Bean实例。

实体Bean (Entity Bean):

创建:通常由容器根据数据库记录创建实体Bean实例。持久化:Bean实例的状态与数据库记录保持同步,容器管理Bean的持久化生命周期。销毁:当数据库记录被删除或 Bean实例不再需要时,容器销毁Bean实例。

五、创建和使用EJB

1. 创建无状态会话Bean

步骤:

定义服务接口:创建一个接口,声明Bean的业务方法。

public interface MyService {

String process(String input);

}

实现接口:创建一个实现该接口的无状态会话Bean类,并使用@Stateless注解标注。

@Stateless

public class MyServiceImpl implements MyService {

@Override

public String process(String input) {

// 实现业务逻辑

return "Processed: " + input;

}

}

部署Bean:将Bean部署到EJB容器中,通常通过在部署描述符中配置或使用IDE的部署功能。

客户端调用:在客户端(如Servlet或其他EJB)中,通过依赖注入或查找获取Bean实例并调用其方法。

@EJB

private MyService myService;

protected void doPost(HttpServletRequest request, HttpServletResponse response) {

String result = myService.process(request.getParameter("input"));

// 处理结果

}

2. 创建有状态会话Bean

步骤:

定义接口:与无状态Bean类似,定义一个接口。

public interface ShoppingCart {

void addItem(String item);

List getItems();

}

实现接口:创建一个实现该接口的有状态会话Bean类,并使用@Stateful注解标注。

@Stateful

public class ShoppingCartImpl implements ShoppingCart {

private List items = new ArrayList<>();

@Override

public void addItem(String item) {

items.add(item);

}

@Override

public List getItems() {

return items;

}

}

客户端调用:客户端通过依赖注入或查找获取Bean实例,并调用其方法。

@EJB

private ShoppingCart shoppingCart;

protected void doPost(HttpServletRequest request, HttpServletResponse response) {

shoppingCart.addItem(request.getParameter("item"));

// 处理购物车

}

管理会话:开发者需要管理会话的生命周期,确保在适当的时候移除Bean实例,避免资源泄漏。可以通过调用@Remove注解标注的方法来显式移除Bean。

@Stateful

public class ShoppingCartImpl implements ShoppingCart {

// ...

@Remove

public void finishShopping() {

// 清理资源

}

}

3. 创建实体Bean (EJB 2.x)

在EJB 2.x中,实体Bean通常与数据库表关联,使用Bean Managed Persistence (BMP)或Container Managed Persistence (CMP)来管理持久化。在EJB 3.x中,实体Bean已被JPA取代,但这里简单介绍一下传统的做法。

步骤:

定义实体接口:创建一个远程接口,声明实体的属性和方法。

public interface User extends EJBObject {

String getUserName();

void setUserName(String userName);

// 其他属性和方法

}

实现接口:创建一个实现远程接口的Bean类,使用@Entity注解标注。

@Entity

public class UserBean implements User {

private String userName;

// 其他属性

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

// 其他方法实现

}

部署Bean:将Bean部署到支持EJB的应用服务器,配置持久化数据源和映射。

客户端调用:客户端通过JNDI查找或依赖注入获取Bean实例,执行CRUD操作。

Context context = new InitialContext();

User user = (User) context.lookup("UserBean/remote");

user.setUserName("johnDoe");

// 其他操作

六. EJB的注解配置

Java EE 5引入注解(Annotations)大大简化了EJB的配置。通过注解,开发者无需编写繁琐的部署描述符文件,直接在代码中标注即可。

常用EJB注解:

@Stateless:标记无状态会话Bean。

@Stateless

public class AuthService {

}

@Stateful:标记有状态会话Bean。

@Stateful

public class ShoppingCart {

}

@Local 和 @Remote:定义Bean的访问范围。

@Local:仅在同一JVM内访问。@Remote:跨JVM访问,适合分布式环境。

@Local

public interface AuthServiceLocal {

}

@EJB:用于注入EJB的引用。

@EJB

private AuthService authService;

@TransactionManagement:定义事务管理类型。

TransactionManagementType.BEAN:Bean管理事务。TransactionManagementType.CONTAINER:容器管理事务(默认)。

@TransactionManagement(TransactionManagementType.CONTAINER)

public class OrderService {

}

@Resource:注入容器管理的资源,如数据源。

@Resource

private DataSource dataSource;

@PostConstruct 和 @PreDestroy:生命周期回调方法。

@PostConstruct

public void initialize() {

// 初始化逻辑

}

@PreDestroy

public void cleanup() {

// 清理逻辑

}

事务管理注解:

@Transactional(Spring)或@TransactionAttribute

(JTA):定义方法的事务属性。

@TransactionAttribute(TransactionAttributeType.REQUIRED)

public void transferFund(Account from, Account to, double amount) {

}

七. 实践:创建简单的EJB组件

本节将通过一个简单的用户管理系统示例,展示如何创建和部署EJB组件。该系统包含一个无状态会话Bean,用于用户的添加和查询。

步骤1:设置开发环境

安装Java EE服务器:如 GlassFish、WildFly或Payara。安装IDE:推荐使用IntelliJ IDEA、Eclipse或NetBeans。添加Java EE和EJB支持:确保IDE已配置Java EE和EJB支持。创建新项目:创建一个Java EE Web项目。

步骤2:创建实体类

首先,创建一个简单的用户实体类。实体类将映射到数据库表,使用JPA注解进行配置。

// src/main/java/com/example/entity/User.java

package com.example.entity;

import jakarta.persistence.*;

import java.io.Serializable;

@Entity

@Table(name = "users")

public class User implements Serializable {

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

@Column(name = "name", nullable = false)

private String name;

@Column(name = "email", nullable = false, unique = true)

private String email;

// Getters and Setters

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

}

步骤3:创建无状态会话Bean

接下来,创建一个无状态会话Bean,封装用户的添加和查询逻辑。

// src/main/java/com/example/ejb/UserService.java

package com.example.ejb;

import com.example.entity.User;

import jakarta.ejb.Stateless;

import jakarta.persistence.EntityManager;

import jakarta.persistence.PersistenceContext;

@Stateless

public class UserService {

@PersistenceContext(unitName = "examplePU")

private EntityManager entityManager;

public void addUser(User user) {

entityManager.persist(user);

}

public List getAllUsers() {

return entityManager.createQuery("SELECT u FROM User u", User.class).getResultList();

}

}

步骤4:配置持久化单元

在 persistence.xml 文件中定义持久化单元,配置数据库连接信息。

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"

version="2.1">

jdbc/exampleDS

false

value="jdbc:mysql://localhost:3306/exampleDB"/>

value="com.mysql.cj.jdbc.Driver"/>

value="root"/>

value="password"/>

步骤5:创建数据源

在应用服务器中配置数据源,连接到数据库。

打开服务器控制台。导航到“JDBC”或“数据源”部分。新建数据源,填写数据库连接信息。测试连接,确保成功。

步骤6:部署EJB组件

将项目打包为EAR或WAR文件,并部署到应用服务器。

使用IDE或Maven构建项目。打开服务器控制台,上传并部署生成的档件。

步骤7:测试EJB服务

创建一个测试客户端,调用EJB的方法进行验证。

// src/test/java/com/example/client/UserClient.java

package com.example.client;

import com.example.entity.User;

import com.example.ejb.UserService;

import jakarta.ejb.embeddable.EJBContainer;

import jakarta.naming.NamingException;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.Test;

import java.util.List;

import static org.junit.Assert.*;

public class UserClient {

private static EJBContainer container;

private static UserService userService;

@BeforeClass

public static void setUp() throws NamingException {

container = EJBContainer.createEJBContainer();

userService = (UserService) container.getContext().lookup("java:global/ExampleApp/UserService!com.example.ejb.UserService");

}

@Test

public void testAddUser() {

User user = new User();

user.setName("John Doe");

user.setEmail("john@example.com");

userService.addUser(user);

List users = userService.getAllUsers();

assertTrue(users.size() > 0);

}

@AfterClass

public static void tearDown() {

container.close();

}

}

步骤8:运行和验证

运行测试用例,验证EJB组件的功能。

添加测试用户。查询所有用户,确保添加成功。检查数据库,确认数据被正确保存。

步骤9:调试和优化

如果出现问题,查看服务器日志,检查配置文件和代码。

常见问题:

数据库连接失败:检查数据源配置和数据库状态。找不到EJB组件:确保Bean正确部署,JNDI名称正确。事务问题:检查事务注解和数据源配置。

步骤10:扩展功能

根据需求,扩展EJB组件的功能,如添加删除和更新方法。

public void deleteUser(Long userId) {

User user = entityManager.find(User.class, userId);

if (user != null) {

entityManager.remove(user);

}

}

public void updateUser(User user) {

entityManager.merge(user);

}

八、EJB 的优势详解

事务管理

EJB容器提供了自动的事务管理,通过使用@TransactionManagement和@TransactionAttribute注解,可以声明式地配置事务属性。例如,可以在方法上使用@TransactionAttribute(TransactionAttributeType.REQUIRED)来标记该方法需要事务支持。

安全性

EJB提供了基于角色的访问控制,可以通过

@RolesAllowed

注解限制访问权限。例如:

@RolesAllowed({"ADMIN"})

public void adminOperation() {

// 只有ADMIN角色的用户可以调用

}

也可以使用@PermitAll和@DenyAll注解来配置更细粒度的安全控制。

资源管理

EJB容器管理资源如数据库连接池、JMS队列等,确保资源的高效利用和正确释放。

例如,可以通过

@Resource

注解注入数据库连接:

@Resource(mappedName = "myDataSource")

private DataSource dataSource;

并发管理

EJB容器负责Bean实例的并发访问,确保在多线程环境下的线程安全。对于无状态Bean,容器可以池化实例,提高响应速度和资源效率。

可扩展性和可维护性

EJB的组件化设计使得应用模块化,各个业务逻辑单元独立开发和测试。通过依赖注入和面向接口编程,提高了代码的可维护性和可扩展性。

九、EJB 的版本演变

EJB经过多次版本更新,每一次版本都带来了新的特性和改进:

EJB 1.0

初始版本,引入了EJB的基本概念,包括会话Bean和实体Bean。需要大量的配置和编码,开发复杂度较高。

EJB 2.0

引入了本地接口和本地会话Bean,简化了Bean的开发。支持更细粒度的事务管理和安全性配置。

EJB 3.0

简化了EJB开发,引入了基于注解的配置,减少了XML配置文件。引入了Java Persistence API (JPA)取代传统的实体Bean,简化了持久化操作。支持依赖注入,提高了开发效率和代码的可维护性。

EJB 3.1

进一步简化了EJB开发,支持无接口的Bean(Bean实现类直接提供方法)。引入了@Singleton注解,支持单例会话Bean。

EJB 3.2

作为Java EE 7的一部分,EJB 3.2引入了对 HTML5和Web Sockets的支持。进一步增强了依赖注入和CDI(Contexts and Dependency Injection)整合。

EJB 4.0 (计划)

预计将进一步简化EJB开发,增强对云计算和微服务的支持。更加紧密地与Java SE 8和9的新特性整合,提升开发效率和性能。

十、常见应用场景

EJB适用于需要高可靠性、可扩展性和复杂业务逻辑的企业级应用场景。以下是一些典型的应用场景:

企业资源规划(ERP)系统:

需要处理复杂的业务流程和数据持久化,EJB的强大的事务管理和持久化支持能够高效处理这些需求。

在线购物平台:

使用有状态会话Bean管理用户的购物车和会话状态,确保用户数据在整个购物过程中的正确性和一致性。

金融交易系统:

依赖EJB的事务管理和安全性特性,确保金融交易的安全性和数据一致性,避免因并发问题导致的资金损失。

库存管理系统:

使用实体Bean或JPA管理库存数据,通过EJB封装业务逻辑,确保数据的正确更新和检索。

CRM(客户关系管理)系统:

管理客户信息和交互记录,利用EJB的持久化和事务管理功能,确保数据的完整性和高效访问。

十一、最佳实践

明确分层:

将应用分为不同的层,如Web层(Servlet、JSP)、业务逻辑层(EJB)、持久化层(JPA、实体Bean)。通过分层设计,确保每一层的职责明确,提高系统的可维护性和扩展性。

遵循单一责任原则:

每个Bean或组件负责单一的功能或责任,避免一个Bean过于复杂,导致维护困难。例如,业务逻辑Bean专注于处理业务规则,而不是直接处理用户界面或数据持久化。

有效利用容器功能:

不要重新发明轮子,尽可能利用EJB容器提供的功能,如事务管理、安全性、资源管理等。避免在Bean中手动管理事务或数据库连接,减少代码复杂性和潜在的错误。

选择合适的Bean类型:

根据具体需求选择合适的EJB类型,避免不当使用。例如,不需要维护会话状态的逻辑应当使用无状态会话Bean,而需要维护会话的使用有状态会话Bean。

优化性能:

合理使用EJB的池化功能,避免过度的Bean实例创建和销毁,提高应用的性能。对于无状态Bean,充分利用池化机制,减少资源消耗。

安全配置:

定义明确的安全角色和权限,通过@RolesAllowed等注解保护Bean的方法,防止未授权访问。合理配置身份认证和授权机制,确保应用的安全性。

测试和验证:

在开发过程中,及时测试和验证EJB的功能,确保Bean的业务逻辑正确,事务管理有效,安全配置合理。使用单元测试、集成测试等方法,全面验证Bean的各项功能和生命周期。

跟踪和监控:

在生产环境中,部署监控工具,跟踪EJB的运行状态、性能指标等,及时发现和解决问题。利用应用服务器提供的监控和管理功能,优化EJB的运行环境,提高系统的稳定性和性能。

十二、总结

Enterprise JavaBeans(EJB)作为Java EE的重要组件,为企业级应用提供了强大的功能和灵活的组件模型。通过合理使用EJB的不同类型和特性,开发者可以高效地封装和管理业务逻辑,简化应用开发,提高系统的可维护性和可扩展性。随着EJB技术的不断发展和Java EE平台的完善,EJB在企业级应用中的应用前景广阔,值得深入学习和掌握。通过实践和项目经验的积累,能够更好地理解和应用EJB技术,提升个人开发能力。

相关推荐

大学的室内设计课程有哪些?
365体育手机版官网

大学的室内设计课程有哪些?

🪐 08-07 👁️ 7777
征信花户什么意思?看看自己征信是怎么花的
诊五笔怎么打
www.bet3365

诊五笔怎么打

🪐 10-09 👁️ 349