34、Java 企业开发:LDAP 与 EJB 技术全解析

Java 企业开发:LDAP 与 EJB 技术全解析

1. 轻量级目录访问协议(LDAP)

LDAP 服务器是专门的软件产品,它以层次树的形式存储目录条目,并且针对读取操作进行了高度优化。这使得它非常适合用于组织中的员工列表或电话目录等目录服务,因为这些目录主要是用于读取,而不是频繁更改,这正是 LDAP 服务器的优势所在。

从企业 Java 的角度来看,当需要快速查找某些 Java 对象时,如 JMS 连接工厂、队列或主题,就应该考虑使用 LDAP 解决方案。Java 开发人员使用 JNDI API 来查找和更新 LDAP 中的条目,就像 JDBC 之于数据库管理系统(DBMS)一样,JNDI 之于 LDAP 服务器。

以下是一些流行的 LDAP 服务器:
| 服务器名称 | 所属公司 | 开源情况 |
| ---- | ---- | ---- |
| Oracle Directory Server | Oracle | 否 |
| Microsoft Active Directory | Microsoft | 否 |
| OpenLDAP | 社区开发 | 是 |
| ApacheDS | Apache | 是 |
| OpenDS | Oracle | 是 |

LDAP 目录树有一个根条目,由一个或多个可分辨名称(唯一标识符)组成。通常,层次结构的顶部是一个以“o”(组织)为前缀的对象,下一级是以“ou”(组织单位)为前缀,“cn”表示通用名称,依此类推。与其他命名服务不同,搜索字符串从层次结构的最底层条目开始,根条目必须最后指定。例如,可用于搜索的可分辨名称如下:

cn=jsmith, ou=accounting, o=oracle.com

这个例子对应于 LDAP 树中的以下层次结构:

o = oracle.com
  ou = accounting
     cn = jsmith

以下代码片段展示了如何准备 JNDI 属性、连接到 LDAP 服务器并查找名为 CustomerHome 的对象:

Hashtable env = new Hashtable();        
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=Directory Manager");
env.put(Context.SECURITY_CREDENTIALS, "myPassword");

DirContext ctx = new InitialDirContext(env);
CustomerHome custHome = (CustomerHome) ctx.lookup("cn=CusomerHome, ou=RealBigProject, o=trump.com");

在实际的分布式应用中,可以有多种构建方式,例如:
1. 计算机 #1 运行 LDAP 服务器。
2. 计算机 #2 运行一个应用服务器,该服务器已将一些对象注册(发布)到计算机 #1 上的 LDAP 服务器。
3. 计算机 #3 有一个客户端程序,它在计算机 #1 上查找对象引用,并在计算机 #2 上调用这些对象的方法。
4. 计算机 #4 有一个数据库管理系统,供计算机 #2 上运行的应用服务器使用。
5. 计算机 #5 发布金融市场数据,计算机 #2 订阅此服务。

graph LR
    A[计算机 #1: LDAP 服务器] --> B[计算机 #2: 应用服务器]
    B --> C[计算机 #3: 客户端程序]
    B --> D[计算机 #4: 数据库管理系统]
    E[计算机 #5: 金融数据发布] --> B
2. 实践:创建消息接收器

可以创建一个名为 MessageReceiver 的类来消费消息。它需要执行 JNDI 查找并开始监听 TestQueue 。当消息到达时, MessageReceiver 应显示该消息。向特定 Servlet 发出请求时,应向队列发送消息, MessageReceiver 接收并打印其内容。

具体步骤如下:
1. 创建一个新类 MessageReceiver ,实现 MessageListener 接口,代码类似于之前的示例,但这次要执行对 MyTestConnectionFactory MyJMSTestQueue 的 JNDI 查找。
2. 了解如何配置 GlassFish 启动类,并实现该类,以便在服务器启动时实例化 MessageReceiver
3. 使用特定的 Servlet 测试发送/接收周期。

3. 企业 JavaBeans(EJB)简介

EJB 是 Java EE 技术之一,可用于在分布式应用中实现业务层。随着 Java EE 6 的发布,EJB 3.1 和 Java 持久化 API(JPA)2.0 为实现业务逻辑和数据持久化提供了简洁的解决方案。支持 EJB 3.1 的应用服务器包括 GlassFish v3、JBoss 6 和 WebSphere 8 等。

为什么需要 EJB 容器呢?虽然可以在普通 Java 对象(POJO)中实现业务逻辑,但可能需要手动编写多线程环境,并且应用可能需要事务支持。例如,如果业务逻辑分布在 POJO 1 和 POJO 2 中,当第二个 POJO 失败时,需要回滚第一个 POJO 已完成的操作。此外,使用 JMS 编写消息接收器时,要实现可扩展性也比较困难。

EJB 容器可以解决这些基础设施相关的问题,无需手动编程。可以简单地配置消息驱动 bean(MDB)池以实现多个消息监听器,根据需要开启事务支持,并且无需担心多线程问题。配置过程只需在 EJB 类中添加 Java 注解,而 bean 之间的通信可以通过依赖注入或单例 bean 实现。

EJB 容器还提供了异步方法调用功能,无需 JMS 或 MOM 即可实现异步处理。此外,EJB 3.1 支持嵌入式容器,可以在 Java SE 环境中运行 EJB 应用,方便进行测试。创建嵌入式容器只需一行代码:

EJBContainer myContainer = EJBContainer.createEJBContainer();
4. EJB 的类型

EJB 主要有两种类型:会话 bean 和消息驱动 bean。消息驱动 bean 专门用于从 JMS 队列或主题中检索消息,而会话 bean 则包含应用的业务逻辑。会话 bean 又分为三种类型:
- 无状态会话 bean :包含业务逻辑,但不支持状态,即不会“记住”特定于客户端的任何数据。例如,同一个客户端连续调用无状态 bean FindBooks 的两个方法时,容器可能会使用 FindBooks bean 的两个不同实例。
- 有状态会话 bean :包含业务逻辑和状态。EJB 容器会为客户端分配一个特定的会话 bean 实例,并可以在后续方法调用之间存储结果。例如,可以使用有状态 bean 实现购物车功能。
- 单例会话 bean :在容器中保证只有一个实例。可以将其视为全局存储库,一个 bean 可以将数据放入其中供另一个 bean 使用,并且可以确保并发访问时没有竞争条件。

早期的 EJB 规范定义了用于数据持久化的实体 bean,但在 EJB 3.1 规范中,它们正在被逐步淘汰,很可能会在未来的 Java EE 版本中消失。

5. 无状态会话 bean

下面通过一个简单的示例介绍无状态会话 bean,该 EJB 包含返回消息“Hello World”的业务逻辑。

Bean 代码示例

@Stateless
public class HelloWorldBean {
    public String sayHello() {
        return "Hello World!";
    }
}

基本上,只需创建一个 POJO 并使用一个或多个 Java 注解进行标注,无需实现特殊接口即可将 POJO 转换为 EJB。还可以使用可选的配置文件 ejb-jar.xml 来指定 EJB 的元数据。

客户端视角
该 bean 在服务器上运行,调用 sayHello() 方法的客户端可以在同一个 JVM 中(如 Servlet 或另一个 bean)运行,也可以在另一个 JVM 中(如独立的 Java SE 应用程序或部署在另一个容器中的 Java EE 类)运行。

如果 HelloWorldBean 仅由在同一 JVM 中运行的客户端使用,可以使用 @LocalBean 注解将其标记为无接口 bean。如果要向本地客户端公开某些业务方法,可以创建一个标记为 @Local 的接口,让 bean 类实现该接口;如果要向远程客户端公开 bean,则创建一个标记为 @Remote 的接口并让 bean 实现它。

本地无接口 bean 示例

import javax.ejb.LocalBean;
import javax.ejb.Stateless;

@LocalBean
@Stateless
public class HelloWorldBean {
    public String sayHello() {
        return "Hello World!";
    }
}

具体操作步骤如下:
1. 在 Eclipse 中创建一个新的动态 Web 项目,命名为 Lesson32
2. 在 com.practicaljava.lesson32.client 包中创建一个新的 Servlet 类 HelloWorldServlet ,该 Servlet 将作为客户端与 EJB 通信。
3. 在 com.practicaljava.lesson32.ejb 包中创建一个 Java 类 HelloWorldBean ,选择“File -> New -> Other -> EJB -> Session Bean (EJB 3.x)”,不选择任何本地或远程业务接口,并取消选中与 EJB 2.x 相关的对象。添加 sayHello() 方法,完成 EJB 的创建。
4. 使用 @EJB 注解将 HelloWorldBean 注入到 Servlet 代码中:

@EJB HelloWorldBean myBean;

如果 Eclipse 标记该行有错误,右键单击并选择“Quick Fix”,自动插入两个导入语句。也可以使用 JNDI 查找来替代注解注入:

Context ctx = new InitialContext();
HelloWorldBean myBean = (HelloWorldBean) ctx.lookup("java:global/Lesson32/HelloWorldBean");
  1. 在 Servlet 的 doGet() 方法中添加以下两行代码,调用 EJB 的 sayHello() 方法:
PrintWriter out = response.getWriter();
out.println(myBean.sayHello()); 

完整的 Servlet 代码示例

import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.practicaljava.lesson32.ejb.HelloWorldBean;

@WebServlet("/HelloWorldServlet")
public class HelloWorldServlet extends HttpServlet {

  @EJB HelloWorldBean myBean;
  protected void doGet(HttpServletRequest request, 
        HttpServletResponse response) throws ServletException, IOException {
       PrintWriter out = response.getWriter();
       out.println(myBean.sayHello());       
  }
}
6. 异步方法

无状态 bean 还有一个重要特性是异步方法。假设 sayHello() 是一个执行长时间计算的方法,希望在调用该方法后继续执行其他操作,而不必等待其完成。在 EJB 容器中,不需要在应用代码中创建和启动线程,因为 EJB 容器会处理所有多线程问题。可以使用 @Asynchronous 注解标记方法,并让其返回 javax.ejb.AsyncResult 对象:

@Asynchronous 
public <Future>String sayHello() {
    // 一些长时间的计算代码
    //... 
    return new AsyncResult<String>("Hello World!");
}

客户端调用 sayHello() 方法后,可以继续执行其他代码,在需要结果时进行阻塞调用 get()

// 异步调用
Future<String> myFutureGreeting = myBean.sayHello();
// 其他代码
//...
// 稍后进行阻塞调用,等待结果
String myGreeting = myFutureGreeting.get();

如果客户端需要在 EJB 上启动多个方法并行运行,这些方法甚至不需要返回值,只需将方法声明为异步并从客户端调用即可。

7. 有状态会话 bean

与无状态会话 bean 不同,有状态会话 bean 会为客户端分配更长时间,并且会记住之前方法执行的结果。例如,可以使用有状态 bean 实现购物车功能,用户在浏览公司目录时可以向购物车中添加多个商品。当客户端结束会话时,有状态 bean 可以分配给另一个客户端。

假设存在一个有状态 EJB MyShoppingCart ,客户端使用 JNDI 查找该 bean 并调用 addItem() 方法添加商品,继续浏览后添加另一个商品,最后调用 placeOrder() 方法结账。所有这些方法调用都在同一个 MyShoppingCart 实例上进行。

MyShoppingCart myCart = (MyShoppingCart) ctx.lookup("java:global/OnlineStore/MyShoppingCart");
// 客户端浏览目录,找到第一个要购买的商品
...
myCart.addItem(myFirstItem);
// 客户端继续浏览目录,找到第二个要购买的商品
...

综上所述,LDAP 和 EJB 是 Java 企业开发中非常重要的技术,它们分别在目录服务和业务逻辑实现方面发挥着关键作用。通过合理使用这些技术,可以构建出高效、可扩展的分布式应用。

Java 企业开发:LDAP 与 EJB 技术全解析

8. 本地与远程 Bean 的区别与应用

在 EJB 开发中,本地 Bean 和远程 Bean 有着不同的应用场景和实现方式。

8.1 本地 Bean

本地 Bean 主要用于在同一 JVM 内的组件之间进行交互。为了向本地客户端暴露业务方法,需要声明一个标记为 @Local 的接口,并让 Bean 类实现该接口。以下是一个示例:

@Local
public interface Greeting {
    public String sayHello();
}

@Stateless
public class HelloWorldBeanL implements Greeting {
    public String sayHello() {
        return "Hello World!";
    }    
}

在这个示例中, Greeting 接口被标记为 @Local HelloWorldBeanL 类实现了该接口。这样,在同一 JVM 内的其他组件就可以通过该接口调用 HelloWorldBeanL 的业务方法。

8.2 远程 Bean

远程 Bean 则用于不同 JVM 之间的交互。对于可能远程访问 Bean 的客户端,需要声明一个标记为 @Remote 的接口,并让 Bean 类实现该接口。示例如下:

@Remote
public interface Greeting {
    public String sayHello();
}

@Stateless
public class HelloWorldBeanL implements Greeting {
    public String sayHello() {
        return "Hello World!";
    }    
}

客户端通过 JNDI 查找来定位远程 Bean。由于客户端和服务器可能运行在不同的 JVM 中,远程方法的所有参数必须是可序列化的。

下面是本地 Bean 和远程 Bean 的对比表格:
| 类型 | 应用场景 | 接口标记 | 调用方式 | 参数要求 |
| ---- | ---- | ---- | ---- | ---- |
| 本地 Bean | 同一 JVM 内组件交互 | @Local | 直接调用 | 无特殊要求 |
| 远程 Bean | 不同 JVM 间交互 | @Remote | JNDI 查找 | 所有参数必须可序列化 |

9. EJB 部署与测试

在开发完 EJB 后,需要将其部署到服务器上进行测试。以 GlassFish 服务器为例,具体步骤如下:
1. 部署项目 :在 Servers 视图中右键单击 GlassFish 服务器,将项目 Lesson32 添加到服务器以部署该 Web 应用。
2. 开启自动部署 :为了避免每次代码更改都手动重新部署应用,可以开启自动部署功能。双击 Servers 视图中的 GlassFish 服务器,将 Publishing 首选项更改为“Automatically publish when resources change”。

graph LR
    A[选择 GlassFish 服务器] --> B[添加项目 Lesson32]
    B --> C[双击服务器]
    C --> D[更改 Publishing 首选项]
    D --> E[自动发布资源更改]
  1. 启动服务器并测试 :启动 GlassFish 服务器(如果未运行),运行 HelloWorldServlet 。可以在浏览器中输入 http://localhost:8080/Lesson32/HelloWorldServlet 查看 EJB 产生的输出。
10. EJB 容器的优势总结

EJB 容器在 Java 企业开发中具有诸多优势,具体如下:
- 基础设施管理 :EJB 容器负责处理多线程、事务支持、消息监听池配置等基础设施相关的问题,开发者无需手动编程,减少了开发工作量和出错的可能性。
- 可扩展性 :通过配置消息驱动 Bean 池和提供集群与故障转移支持,EJB 容器能够轻松应对分布式应用的扩展需求。
- 安全性 :安全授权由 EJB 容器负责,确保了应用的安全性。
- 异步处理 :支持异步方法调用,无需额外的 JMS 或 MOM 即可实现异步处理,提高了应用的性能和响应速度。
- 嵌入式容器 :EJB 3.1 支持嵌入式容器,可在 Java SE 环境中运行 EJB 应用,方便进行测试。

11. 总结与实践建议

在 Java 企业开发中,LDAP 和 EJB 技术是构建高效、可扩展分布式应用的重要工具。LDAP 服务器适用于存储和快速查找目录信息,如员工列表、电话目录等;而 EJB 则用于实现分布式应用的业务逻辑,通过 EJB 容器可以解决多线程、事务管理、消息处理等复杂问题。

为了更好地应用这些技术,建议开发者:
1. 深入学习 JNDI :掌握 JNDI 的使用方法,它是连接 LDAP 服务器和 EJB 客户端的桥梁。
2. 合理选择 EJB 类型 :根据业务需求选择合适的 EJB 类型,如无状态会话 Bean 适用于多用户并发请求的场景,有状态会话 Bean 适用于需要保存客户端状态的场景。
3. 利用 EJB 容器特性 :充分利用 EJB 容器提供的基础设施管理、可扩展性、安全性等特性,减少开发工作量,提高应用的质量和性能。
4. 多进行实践 :通过实际项目的开发,加深对 LDAP 和 EJB 技术的理解和掌握。

总之,通过合理运用 LDAP 和 EJB 技术,开发者可以构建出更加高效、稳定、安全的 Java 企业应用。

胚胎实例分割数据集 一、基础信息 • 数据集名称:胚胎实例分割数据集 • 图片数量: 训练集:219张图片 验证集:49张图片 测试集:58张图片 总计:326张图片 • 训练集:219张图片 • 验证集:49张图片 • 测试集:58张图片 • 总计:326张图片 • 分类类别: 胚胎(embryo):表示生物胚胎结构,适用于发育生物学研究。 • 胚胎(embryo):表示生物胚胎结构,适用于发育生物学研究。 • 标注格式:YOLO格式,包含实例分割的多边形标注,适用于实例分割任务。 • 数据格式:图片来源于相关研究领域,格式为常见图像格式,细节清晰。 二、适用场景 • 胚胎发育AI分析系统:构建能够自动分割胚胎实例的AI模型,用于生物学研究中的形态变化追踪和量化分析。 • 医学生物研究:在生殖医学、遗传学等领域,辅助研究人员进行胚胎结构识别、分割和发育阶段评估。 • 学术创新研究:支持计算机视觉生物医学的交叉学科研究,推动AI在胚胎学中的应用,助力高水平论文发表。 • 教育实践培训:用于高校或研究机构的实验教学,帮助学生和从业者掌握实例分割技术及胚胎学知识。 三、数据集优势 • 精准专业性:实例分割标注由领域专家完成,确保胚胎轮廓的精确性,提升模型训练的可靠性。 • 任务专用性:专注于胚胎实例分割,填补相关领域数据空白,适用于细粒度视觉分析。 • 格式兼容性:采用YOLO标注格式,易于集成到主流深度学习框架中,简化模型开发部署流程。 • 科学价值突出:为胚胎发育研究、生命科学创新提供关键数据资源,促进AI在生物学中的实际应用。
物品实例分割数据集 一、基础信息 • 数据集名称:物品实例分割数据集 • 图片数量:训练集1441张、验证集167张、测试集172张,总计1780张图片 • 分类类别:物品(item) • 标注格式:YOLO格式,包含实例分割的多边形标注,适用于实例分割任务 • 数据格式:图片数据,来源于多样场景 二、适用场景 • 物品实例分割AI系统开发:支持构建能够自动识别并精确分割物品轮廓的AI模型,应用于自动化检测和识别系统。 • 物流仓储管理:用于物品的分割和定位,提升库存管理、货物追踪和物流效率。 • 制造业质量检查:在制造过程中,对零件或产品进行实例分割,辅助质量评估和生产流程优化。 • 零售行业应用:集成至零售系统中,实现商品自动分割和识别,优化库存管理和用户体验。 • 学术研究创新:支持计算机视觉领域的研究,特别是在实例分割任务上的模型开发和性能评估。 三、数据集优势 • 精准标注:每个物品实例均采用多边形标注,精确捕捉轮廓细节,确保分割准确性和可靠性。 • 数据多样性:数据集覆盖多种场景下的物品图片,增强模型在不同环境下的泛化能力和适应性。 • 任务专用:专注于实例分割任务,标注兼容YOLO等主流深度学习框架,便于模型训练和部署。 • 实用性强:适用于实际工业和应用场景,为物品分割相关AI开发提供高质量数据支撑,加速模型迭代。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值