1. 概述

本文将带你入门 Enterprise JavaBean (EJB) 开发。EJB 专用于构建可扩展、分布式、服务端组件,通常用于封装应用的核心业务逻辑。

我们将使用 WildFly 10.1.0 作为演示服务器,当然你也可以选择任何其他 Java EE 应用服务器。

2. 环境搭建

先介绍 EJB 3.2 开发所需的 Maven 依赖,以及如何通过 Maven Cargo 插件或手动方式配置 WildFly 服务器。

2.1 Maven 依赖

pom.xml 中添加最新版 EJB 3.2 依赖:

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

2.2 使用 Maven Cargo 设置 WildFly

通过 Maven Cargo 插件自动化服务器配置:

<profile>
    <id>wildfly-standalone</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
                <version>${cargo-maven2-plugin.version}</version>
                <configuration>
                    <container>
                        <containerId>wildfly10x</containerId>
                        <zipUrlInstaller>
                            <url>
                                http://download.jboss.org/
                                  wildfly/10.1.0.Final/
                                    wildfly-10.1.0.Final.zip
                            </url>
                        </zipUrlInstaller>
                    </container>
                    <configuration>
                        <properties>
                            <cargo.hostname>127.0.0.1</cargo.hostname>
                            <cargo.jboss.management-http.port>
                                9990
                            </cargo.jboss.management-http.port>
                            <cargo.servlet.users>
                                testUser:admin1234!
                            </cargo.servlet.users>
                        </properties>
                    </configuration>
                </configuration>
            </plugin>
        </plugins>
    </build>
</profile>

此配置会:

  1. 自动下载 WildFly 10.1
  2. 设置主机为 127.0.0.1,管理端口为 9990
  3. 创建测试用户 testUser(密码 admin1234!

执行以下命令启动服务器:

mvn clean package cargo:run

首次运行会下载并安装服务器,后续启动会复用已下载文件。

2.3 手动设置 WildFly

手动安装步骤:

  1. wildfly.org 下载安装包
  2. 解压到目标目录后配置环境变量:
    JBOSS_HOME=/Users/yourname/wildfly-10.1.0.Final
    JAVA_HOME=`/usr/libexec/java_home -v 1.8`
    
  3. bin 目录执行:
    • Linux: ./standalone.sh
    • Windows: standalone.bat
  4. 添加管理用户(参考官方文档

详细配置见 WildFly 入门指南

项目 POM 配置了两种部署方式:

  • 默认使用 Cargo 插件
  • 手动部署到已运行服务器:
    mvn clean install wildfly:deploy -Pwildfly-runtime
    

3. Remote 与 Local 接口

EJB 业务接口分为两种类型:

类型 特性
@Local 仅限同一应用内访问(如同一 .ear 或 .war)
@Remote 可跨应用访问(不同 JVM 或服务器)

设计时需注意:

  • java.io.Serializablejava.io.Externalizablejavax.ejb 包接口始终被排除
  • ✅ 类标记为 @Remote 时,所有实现接口自动成为远程接口
  • ✅ 未标注或标注 @Local 时,所有接口默认为本地
  • ✅ 无接口的 Bean 必须显式声明 @Local
  • ⚠️ EJB 3.2 提供更细粒度的接口控制能力

4. 创建 Remote EJB

先定义业务接口 HelloWorld

@Remote
public interface HelloWorld {
    String getHelloWorld();
}

实现类 HelloWorldBean

@Stateless(name = "HelloWorld")
public class HelloWorldBean implements HelloWorld {

    @Resource
    private SessionContext context;

    @Override
    public String getHelloWorld() {
        return "Welcome to EJB Tutorial!";
    }
}

关键点:

  • @Stateless 注解声明无状态会话 Bean
    • 不维护客户端状态
    • 可能保留实例状态
    • 适合执行独立操作
  • @Resource 注入 SessionContext
    • 提供运行时会话上下文访问
    • 容器在实例创建后注入
    • 生命周期内与实例绑定

⚠️ 由于容器使用对象池机制,实例变量值在多次调用间可能不保持。

5. 远程部署配置

5.1 EJB 插件配置

使用 Maven EJB 插件打包模块:

<plugin>
    <artifactId>maven-ejb-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <ejbVersion>3.2</ejbVersion>
    </configuration>
</plugin>

5.2 部署 Remote EJB

确保 WildFly 服务器运行后,在 ejb-remote 项目目录执行:

mvn wildfly:deploy

或通过管理控制台手动部署(需管理员权限)。

6. JNDI 查找机制

6.1 查找方法实现

public HelloWorld lookup() throws NamingException { 
    String appName = ""; 
    String moduleName = "remote"; 
    String distinctName = ""; 
    String beanName = "HelloWorld"; 
    String viewClassName = HelloWorld.class.getName();
    String toLookup = String.format("ejb:%s/%s/%s/%s!%s",
      appName, moduleName, distinctName, beanName, viewClassName);
    return (HelloWorld) context.lookup(toLookup);
}

6.2 关键参数说明

  • Context Factory:由 org.jboss:jboss-remote-naming 提供
  • JNDI 上下文:将 URL 解析为远程服务器代理

6.2.1 必需参数

# 上下文工厂类
java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory

# 包扫描前缀
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming

# 禁用类路径配置
org.jboss.ejb.client.scoped.context=false

# 连接协议
java.naming.provider.url=http-remoting://127.0.0.1:8080

⚠️ org.jboss.ejb.client.scoped.context=false 强制从提供的参数读取连接配置(而非类路径文件),这对多环境部署至关重要。

7. 测试验证

@Test
public void testEJBClient() {
    EJBClient ejbClient = new EJBClient();
    HelloWorldBean bean = new HelloWorldBean();
    
    assertEquals(bean.getHelloWorld(), ejbClient.getEJBRemoteMessage());
}

测试通过即表示远程调用链路正常。

8. 总结

我们成功实现了:

  1. EJB 服务器端开发
  2. 远程客户端调用
  3. 跨 JVM 方法调用

完整项目代码见 GitHub 仓库。通过调整服务器依赖,可轻松迁移到其他 Java EE 应用服务器。


原始标题:Guide to EJB Set-up

« 上一篇: Guava RangeSet 使用