Jakarta EE 编程/Jakarta Enterprise Beans
EJB 代表 Enterprise JavaBeans。新手不要将其与 Core Java 的 Java Beans 混淆。
此页面介绍 Enterprise JavaBeans 2.1。它还涵盖了 EJB 2.0,后者仍在广泛使用。正如 Java 平台彻底改变了我们对软件开发的思考方式一样,Enterprise JavaBeans 彻底改变了我们对开发关键任务企业软件的思考方式。它将服务器端组件与分布式对象技术、异步消息传递和 Web 服务相结合,极大地简化了应用程序开发任务。它自动考虑了业务系统的许多要求,包括安全、资源池、持久性、并发和事务完整性。
本书将向您展示如何使用 Enterprise JavaBeans 开发可扩展、可移植的业务系统。但在我们开始讨论 EJB 本身之前,我们需要简要介绍一下 EJB 所涉及的技术,例如组件模型、分布式对象、异步消息传递和 Web 服务。尤其需要了解组件事务监视器,即 EJB 底层技术。
假设您已经熟悉 Java;如果您不熟悉,请先阅读 Java 编程。本书还假设您熟悉 JDBC API,或者至少熟悉 SQL。如果您不熟悉 JDBC,请参阅 使用 SQLite 的 Java JDBC。
Java 最重要的特性之一是平台独立性。自首次发布以来,Java 一直被宣传为“一次编写,随处运行”。虽然炒作有时有点过分,但使用 Sun 的 Java 编程语言编写的代码在平台之间具有非凡的独立性。Enterprise JavaBeans 不仅是平台独立的,而且是实现独立的。如果您使用过 JDBC,那么您对这意味着什么有一点了解。JDBC API 不仅可以在 Windows 机器或 Unix 机器上运行,还可以通过使用不同的 JDBC 驱动程序访问许多不同供应商的关系数据库(DB2、Oracle、MySQL、SQLServer 等)。您无需针对特定数据库实现进行编码——只需更改 JDBC 驱动程序,即可更改数据库。EJB 也是如此。理想情况下,EJB 组件(企业 Bean)可以在实现 EJB 规范的任何应用程序服务器中运行。这意味着您可以在一个服务器(例如 BEA 的 WebLogic)中开发和部署您的 EJB 业务系统,然后将其移动到另一个 EJB 服务器,例如 Pramati、Sybase EAServer、IBM 的 WebSphere 或开源项目,如 Apache Geronimo、OpenEJB、JOnAS 或 JBoss。实现独立性意味着您的业务组件不依赖于服务器品牌,这为您在开发和部署之前、期间和之后提供了更多选择。
除了支持分布式业务对象外,Enterprise JavaBeans 还支持异步消息传递。EJB 2.1 还允许将企业 Bean 作为 Web 服务公开,以便其他 J2EE 应用程序以及在各种平台上用其他编程语言编写的应用程序可以调用其方法。EJB 2.1 中的 Web 服务支持 RPC 样式和文档样式的消息传递。对 Web 服务的支持基于新的 Web 服务 API:JAX-RPC。
面向对象的语言(如 Java、C++ 和 C#)用于编写灵活、可扩展和可重用的软件——面向对象开发的三个公理。在业务系统中,面向对象的语言用于改进 GUI 的开发、简化对数据的访问以及封装业务逻辑。将业务逻辑封装到业务对象中是信息技术行业最近的重点。业务是流动的,这意味着企业的商品、流程和目标会随着时间的推移而发展。如果模拟业务的软件可以封装到业务对象中,它将变得灵活、可扩展和可重用,从而随着业务的发展而发展。
服务器端组件模型可以定义一个用于开发分布式业务对象的架构,该架构将分布式对象系统的可访问性与对象化业务逻辑的灵活性相结合。服务器端组件模型用于中间层应用程序服务器,这些服务器在运行时管理组件并使它们可供远程客户端使用。它们提供了基本的功能,使开发分布式业务对象并将其组装成业务解决方案变得容易。
服务器端组件也可用于模拟业务系统的其他方面,例如表示和路由。例如,Java servlet 是一个用于为三层架构的表示层生成 HTML 和 XML 数据的服务器端组件。本书后面将讨论的 EJB 2.1 消息驱动 Bean 是可以用于使用和处理异步消息的服务器端组件。
服务器端组件与其他组件一样,可以作为独立的可执行软件进行买卖。它们符合标准组件模型,并且可以在支持该组件模型的服务器中执行,无需直接修改。服务器端组件模型通常支持基于属性的编程,允许在部署组件时修改组件的运行时行为,而无需更改组件中的编程代码。根据组件模型的不同,服务器管理员可以通过将这些属性设置为特定值来声明服务器端组件的事务、安全甚至持久性行为。
随着组织的服务、产品和操作流程的发展,可以重新组装、修改和扩展服务器端组件,以便业务系统反映这些变化。想象一下,一个业务系统是一组模拟客户、产品、预订和仓库等概念的服务器端组件。每个组件都像一个乐高积木,可以与其他组件组合起来构建业务解决方案。产品可以存储在仓库中或交付给客户;客户可以预订或购买产品。您可以组装组件、拆卸组件、以不同的组合使用组件并更改其定义。基于服务器端组件的业务系统是流动的,因为它被对象化了,并且它是可访问的,因为组件可以被分布。
Oracle 对 Enterprise JavaBeans 的定义是
- “Enterprise JavaBeans 架构是用于开发和部署基于组件的分布式业务应用程序的组件架构。使用 Enterprise JavaBeans 架构编写的应用程序是可扩展的、支持事务的和多用户安全的。这些应用程序可以编写一次,然后部署在任何支持 Enterprise JavaBeans 规范的服务器平台上。”
这很拗口,但对于 Sun 如何定义其许多 Java 技术来说并不典型——您是否曾经阅读过 Java 语言本身的定义?大约长两倍。本书对 EJB 提供了一个更简短的定义
Enterprise JavaBeans 是用于分布式业务应用程序的标准服务器端组件模型。
这意味着 EJB 提供了一个标准模型,用于构建表示业务对象(客户、库存中的商品等)和业务流程(购买、库存等)的服务器端组件。构建出一组符合业务需求的组件后,您可以将它们组合起来创建业务应用程序。最重要的是,作为“分布式”组件,它们不必都驻留在同一台服务器上:组件可以驻留在最方便的位置:Customer 组件“驻留”在 Customer 数据库附近,Part 组件可以“驻留”在库存数据库附近,而 Purchase 业务流程组件可以“驻留”在用户界面附近:您可以执行任何必要的操作以最大程度地减少延迟、共享处理负载或最大化可靠性。
要了解 EJB,您需要了解分布式对象的工作原理。分布式对象系统是现代三层架构的基础。在三层架构中,如图 1-1 所示,表示逻辑驻留在客户端(第一层),业务逻辑驻留在中间层(第二层),其他资源(如数据库)驻留在后端(第三层)。
所有分布式对象协议都构建在相同的基本架构之上,该架构旨在使一台计算机上的对象看起来像驻留在另一台计算机上。分布式对象架构基于非常简单的网络通信层。本质上,此架构由三个部分组成:业务对象、骨架和存根。
业务对象驻留在中间层。它是对象的一个实例,用于模拟某个现实世界概念的状态和业务逻辑,例如人员、订单或帐户。每个业务对象类都具有与其匹配的存根和骨架类,这些类专门为该类型的业务对象构建。例如,一个名为Person
的分布式业务对象将具有匹配的PersonStub
和PersonSkeleton
类。如图1-2所示,业务对象和骨架驻留在中间层,而存根驻留在客户端。
存根和骨架负责使中间层的业务对象看起来好像在客户端机器上本地运行。这是通过某种远程方法调用(RMI)协议实现的。RMI协议用于通过网络通信方法调用。CORBA、Java RMI和Microsoft .NET都使用自己的协议。中间层上每个业务对象的实例都由其匹配的骨架类的实例包装。骨架在端口和IP地址上设置并侦听来自存根的请求,存根驻留在客户端机器上并通过网络连接到骨架。存根充当客户端上业务对象的代理,并负责通过骨架将客户端的请求传达给业务对象。图1-2说明了从客户端到服务器对象再返回的方法调用通信过程。存根和骨架分别向客户端和实现类隐藏了RMI协议的通信细节。
业务对象实现一个公共接口,该接口声明其业务方法。存根实现了与业务对象相同的接口,但存根的方法不包含业务逻辑。相反,存根上的业务方法实现将请求转发到业务对象并接收结果所需的任何网络操作。当客户端在存根上调用业务方法时,请求通过网络通信,将调用的方法名称和作为参数传递的值流式传输到骨架。当骨架接收传入流时,它会解析流以发现请求哪个方法,然后在业务对象上调用相应的业务方法。从业务对象上调用的方法返回的任何值都由骨架流式传输回存根。然后,存根将该值返回给客户端应用程序,就好像它在本地处理了业务逻辑一样。
术语“组件模型”有很多不同的解释。Enterprise JavaBeans指定了一个服务器端组件模型。使用javax.ejb
包中的一组类和接口,开发人员可以创建、组装和部署符合EJB规范的组件。最初的JavaBeans™也是一个组件模型,但它不是像EJB那样的服务器端组件模型。事实上,除了共享“JavaBeans”这个名称之外,这两个组件模型完全无关。过去,很多文献将EJB称为原始JavaBeans的扩展,但这是一种误传。这两个API服务于截然不同的目的,EJB既不扩展也不使用原始的JavaBeans。
JavaBeans旨在用于进程内目的,而EJB则专为进程间组件设计。换句话说,最初的JavaBeans并非旨在用于分布式组件。JavaBeans可用于解决各种问题,但它主要用于通过组装视觉(GUI)和小部件来构建客户端。它是一个优秀的组件模型,可能是迄今为止为进程内开发设计的最佳模型,但它不是服务器端组件模型。另一方面,EJB明确旨在解决在三层体系结构中管理分布式业务对象所涉及的问题。
鉴于JavaBeans和Enterprise JavaBeans完全不同,为什么它们都被称为组件模型?在此上下文中,组件模型定义了组件开发人员与托管组件的系统之间的一组契约。这些契约表达了如何开发和打包组件。一旦定义了组件,它就会成为可以分发并在其他应用程序中使用的独立软件。组件是为特定目的开发的,而不是为特定应用程序开发的。在原始的JavaBeans中,组件可能是按钮或电子表格,可以根据原始JavaBeans组件模型中指定的规则用于任何GUI应用程序。在EJB中,有几种不同类型的组件:表示数据库中实体的组件(实体Bean)与其容器的契约略有不同,而表示业务流程的组件(会话Bean)则不同。例如,组件可能是由实体Bean表示的“客户”业务对象,可以部署在任何EJB服务器中,并用于开发任何需要客户业务对象的业务应用程序。另一种类型的组件可能是由会话Bean表示的MakePurchase
对象,该对象模拟客户购买特定产品时发生的情况。(尽管购买行为本身并未在数据库中表示,但购买涉及客户、销售人员、库存、应收账款以及可能的其他实体之间的复杂交互)。MakePurchase
对象与其容器的契约不同于Customer
对象,但它也可以部署在任何EJB服务器中,并在任何需要支持购买的业务应用程序中使用。第三种类型的EJB,MessageDrivenBean,与其容器的契约略有不同,但它也可以部署在任何EJB服务器中。
Enterprise JavaBeans并非凭空出现;它是众多组件事务监视器 (CTM) 之一,而CTM又源于更旧的事务处理监视器(如Tuxedo)和对象请求代理。但是,EJB 最重要的竞争对手是 Microsoft 的 .NET 框架。.NET 的起源可以追溯到 Microsoft 事务服务器 (MTS),它可以说是第一个商用 CTM。MTS 后来更名为 COM+。Microsoft 的 COM+ 基于组件对象模型 (COM),最初设计用于桌面使用,但最终被用作服务器端组件模型。对于分布式访问,COM+ 客户端使用分布式组件对象模型 (DCOM)。
当 MTS 于 1996 年推出时,这是一个令人兴奋的发展,因为它为业务对象提供了一个全面的环境。使用 MTS,应用程序开发人员可以编写 COM 组件,而无需担心系统级问题。一旦业务对象设计为符合 COM 模型,MTS(现在是 COM+)就会处理所有其他事情,包括事务管理、并发和资源管理。
COM+ 已成为 Microsoft 新 .NET 框架的一部分。COM+ 服务提供的核心功能在 .NET 中基本保持不变,但开发人员看到的方式发生了重大变化。.NET 框架开发人员不是将组件编写为 COM 对象,而是将应用程序构建为托管对象。所有托管对象,实际上是为 .NET 框架编写的所有代码,都依赖于公共语言运行时 (CLR)。对于面向 Java 的开发人员,CLR 非常类似于 Java 虚拟机 (VM),而托管对象类似于 Java 类的实例;即 Java 对象。
.NET 框架通过 SOAP (简单对象访问协议) 协议提供一流的 Web 服务支持,这使得 .NET 世界中的业务组件能够与用任何语言编写的任何其他平台上的应用程序通信。这可能使 .NET 中的业务组件能够普遍访问,这是一个不容忽视的功能。事实上,.NET 是促使 Sun Microsystems 扩展 EJB 和 J2EE 平台其余部分以支持 Web 服务的动力。自 1995 年推出 Java 编程语言以来,Microsoft 的 .NET 平台对 Java 平台的主导地位构成了最大的威胁。
尽管 .NET 框架提供了许多有趣的功能,但它作为开放标准却有所欠缺。.NET 框架中的 COM+ 服务是 Microsoft 的专有 CTM,这意味着使用此技术会将您绑定到 Microsoft 平台。如果您的公司计划在非 Microsoft 平台上部署服务器端组件,则 .NET 不是可行的解决方案。此外,.NET 框架中的 COM+ 服务专注于无状态组件;没有内置对持久性事务对象的支持。尽管无状态组件可以提供更高的性能,但业务系统需要 CTM 提供的那种灵活性,其中包括有状态和持久性组件。
什么是标准的服务器端组件模型?简单来说,这意味着您可以使用 Enterprise JavaBeans 组件模型开发业务对象,并期望它们在任何支持完整 EJB 规范的应用服务器上都能正常工作。这是一个非常强大的声明,因为它在很大程度上消除了 Microsoft .NET 产品潜在客户面临的最大问题:对供应商“锁定”的恐惧。使用标准的服务器端组件模型,客户可以承诺使用符合 EJB 规范的应用服务器,并知道如果出现更好的服务器,他们可以迁移到该服务器。显然,在使用供应商开发的专有扩展时必须小心,但这并不是什么新鲜事。即使在关系数据库行业——几十年来一直在使用 SQL 标准——也存在大量的可选专有扩展。
拥有一个标准的服务器端组件模型除了实现独立性之外还有其他好处。标准组件模型为第三方产品的增长提供了途径。如果众多供应商支持 EJB,那么创建附加产品和组件库对软件供应商来说更有吸引力。IT 行业已经看到这种类型的家庭作坊围绕其他标准(例如 SQL)发展起来;现在可以购买数百种附加产品来增强存储在符合 SQL 规范的关系数据库中的数据的业务系统。报表生成工具和数据仓库产品就是典型的例子。GUI 组件行业也见证了其自身第三方产品的增长。对于 Sun 最初的 JavaBeans 组件模型等 GUI 组件模型,已经存在一个健康的组件库市场。
今天,许多针对 Enterprise JavaBeans 的第三方产品存在。已经为各种兼容 EJB 的系统引入了用于信用卡处理、遗留数据库访问和其他业务服务的附加产品。这些类型的产品使 EJB 系统的开发比替代方案更简单、更快,从而使 EJB 组件模型对企业 IS 和服务器供应商都具有吸引力。预打包 EJB 组件的市场在多个领域不断增长,包括销售、金融、教育、网站内容管理、协作以及其他领域。
为了使事情变得更容易,也更有趣,我们将在这本书中讨论所有概念,并将其置于一家名为“泰坦”的虚构邮轮公司的背景下。邮轮公司是一个特别有趣的例子,因为它包含了几种不同的业务:它拥有类似于酒店房间的船舱,它像餐厅一样提供餐点,它提供各种娱乐机会,并且需要与其他旅行业务互动。
这种类型的企业非常适合分布式对象系统,因为许多系统的用户在地理上分散。例如,需要预订泰坦船只航程的商业旅行社需要访问预订系统。支持许多(可能是数百个)旅行社需要一个强大的事务系统来确保代理商能够访问并正确完成预订。在本书中,我们将构建泰坦 EJB 系统的一个相当简单的片段,重点关注预订邮轮的过程。此练习将使我们有机会开发 Ship、Cabin、TravelAgent、ProcessPayment 等企业 Bean。在此过程中,您需要创建关系数据库表以持久化示例中使用的数据。假设您熟悉关系数据库管理系统,并且可以根据提供的 SQL 语句创建表。EJB 可以与任何类型的数据库或遗留应用程序一起使用,但关系数据库似乎是最常用的数据库,因此我选择它作为持久层。
要使用 EJB 开发业务对象,您必须了解 EJB 组件的生命周期和体系结构。这意味着从概念上理解 EJB 的组件是如何管理以及如何作为分布式对象提供的。