上一章通过开发一个简单的企业Bean,对EJB有了一个初步的认识,本章进一步讨论EJB技术体系的主要几个方面,阐述诸如EJB组件、EJB角色、EJB类型、持久性、EJB合约等基本概念。使读者对EJB技术有更加深入的了解。
企业Bean(Enterprise JavaBeans,EJB)规范由SUN公司和其它伙伴公司制订,1.0版本在1998年3月发布。1.1版本在1999年12月发布。最近的版本是2.0,于2000年10月发布。可以从网址http://java.sun.com/products/ejb/docs.html下载该规范。
本章以Enterprise JavaBeans(EJB)规范2.0版为主要参考,从多个侧面介绍EJB的基本概念。
3.1 EJB组件
企业Bean技术从本质上说是一个基于组件的分布式计算架构体系规范。企业Bean是分布式的面向业务逻辑的企业应用组件。
基于组件的应用方式是把传统上的应用系统按一定的目标分成两个部分:容器和组件。这种划分更多的是从功能出发的,划分的原则把底层技术细节与应用逻辑分开。容器部分重点在于解决底层的技术问题,如目录访问、分布式事务处理、安全管理、并行访问、持久性管理、资源池管理、系统管理界面和负载均衡等方面。组件部分重点放在具体的应用逻辑上。同时,这样划分也把不同性质的开发工作分离出来。具有不同技术背景的开发人员关注于系统的某一个层面而无需对其他层面深人的了解。一旦这种划分成为了一个技术标准,那么就形成了相关的技术领域的社会工业。
3.1.1 EJB组件的特性
企业Bean的重要特性如下:
·企业Bean包括操作企业数据的业务逻辑。企业Bean是用来封装业务逻辑的。
·企业Bean的实例被容器创建和运行。容器管理EJB。
·企业Bean在部署的时候通过编辑环境属性来定制。使用部署描述符是部署EJB的重要环节。
·不同的服务信息,如事务和安全属性,从企业Bean类中分离出来。这些通用的服务由容器一次完成。开发不同的应用时,不必再考虑这些琐碎的细节问题。用一些工具在应用程序装配和部署过程中管理服务信息。
·客户端访问部署在容器的组件是快速进行的。容器通过使用资源池等手段显著提高了性能。
·如果一个企业Bean仅使用EJB规范定义的服务,它能被部署在任何一个兼容的EJB容器中。特定的容器能提供EJB额外的服务。依赖这样服务的企业Bean只能部署在支持这个服务的容器中。EJB规范是个通用的规范,得到很多厂商的支持,确保了EJB的可移植性。
·企业Bean能被包含在一个已装配的应用程序中,而不需源代码的改变或重新编译。具有良好的重构性、可升级特征。
·Bean提供者定义一个企业Bean的客户端视图。Bean提供者可以手工定义客户端视图或通过程序部署工具自动产生。客户端视图不受Bean部署的容器和服务器的影响。这确保了Bean和它们的客户端能被部署到多种执行环境中而不需改变或重新编译。
3.1.2 EJB组件的类型
企业Bean架构是灵活的,可以实现下列组件:
·表示一个无状态服务的对象。即无状态会话EJB。
·表示一个无状态服务对象且是异步激发的,被Java消息服务(JMS)的消息驱动。即消息驱动Bean。
·表示一个特定客户端的会话状态的对象。如会话对象在客户端多次调用之间自动维持它们的会话状态。即有状态会话Bean。
·实体对象表示商业逻辑对象,被多个客户端共享。即实体Bean。实体Beans用来描述较粗糙的逻辑对象(如订单、雇员记录等)。不太适合描述较详细的对象(如订单上的项、雇员地址等)。
EJB的状态是个较重要的概念。这里的状态是在EJB的客户端视图定义的,也就是说EJB的状态指的是EJB呈现的客户端的状态,而并不是指EJB本身的生存状态,这两者往往并不完全一致。
虽然EJB定义的状态管理协议简单,它为开发者提供了一个在管理状态上的企业Bean极大的灵活性。
3.1.3 企业 Beans组件应用模型
J2EE三层应用架构定义了两种基于组建的应用模式,即Web应用和EJB应用。如表3-1所示。
表3-1 Web应用与EJBs应用对比
─────────────────────────────────
Web应用 EJBs应用
─────────────────────────────────
组件 Servlets(Jsps) EJBs
容器 包含在Web服务器中 在应用服务器中
通信协议 Http Java RMI,CORBA IIOP,
Microsoft DCOM等
─────────────────────────────────
这里我们考虑EJBS应用的情况(Web应用在第7、8章讨论)。
如图3-1所示是EJB组件运行架构图。图中间的部分包括EJB容器和部署在容器中的组件(即EJB)。图左边的部分是EJB的客户端。图中共示意了四种客户端。EJB还有一种重要的客户端类型,就是EJB本身。也就是说,一个EJB组件可以作为另一个EJB组件的客户端。这种情况在企业级应用中是很常见的。
客户端也可以简单的分成两种:即Java客户端和非Java客户端(比如C/C++)。对Java客户端来说,传输协议可以采用 Java远程方法调用(Java RMI)方式,也可以是IIOP协议,而对非Java客户端来说,只能采用IIOP协议。
3.2 EJB角色
围绕EJB应用(包括组件和容器)的开发和部署周期,EJB规范为EJB架构定义了七个角色,每个角色由不同的单位承担。EJB规范通过定义角色者之间的“合约”,来确保角色间的正确协作。在某些时候,某个组织可以同时具有多个角色。比如某个公司会提供包含EJB服务器和容器的产品,那么它同时充当着EJB服务器提供者和容器提供者两种角色。因此,这种角色划分并不是绝对的。
以下是EJB规范2.0中定义的EJB角色。
1.EJB提供者
EJB提供者,即EJB的开发者。对于多数企业级应用开发者来说,都属于这个角色。EJB提供者的产品是个包含一个或多个EJB的打包文件(即ejb-jar文件)。EJB提供者负责业务逻辑方法的 Java语言实现;定义EJB的远程和主接口方法和EJB的部署描述符。部署描述符包括EJB的结构信息(如EJB类的名字)和EJB用到的其它所用资源的描述信息。
EJB提供者是个应用领域的专家。负责开发实现业务任务和逻辑实体的可重用的EJB。不必是系统级的程序专家,也不必考虑程序的事务并发性、安全性、分布性等问题,这些问题都是由容器解决的。
2. EJB应用装配者
应用装配者把EJB装配成更大的可部署的应用单元。有时这个工作也由EJB提供者完成。EJB装配者的输入是EJB提供者生产的一个或多个ejb-jar文件,输出是一个或多个包含EJB和应用装配信息的ejb-jar文件。前者ejb-jar文件的扩展名一般是JAR(Java Archive),后者ejb-jar文件的扩展名可以是WAR(Web Application Archive)或EAR(Enterprise Application Archive)。应用装配者把应用装配信息插入到部署描述符中。
应用装配者也可以把其它应用类型的组件(如JSP,JavaServerPage)装配到EJB应用中(这就象在PetStore例子中看到的那样)。
应用装配者工作的对象是EJB部署描述符和EJB客户端视图合约。虽然他必须熟悉EJB的远程接口和主接口,但他不必具有任何实现EJB开发的知识。
3.EJB部署者
部署者把从EJB提供者和应用装配者那里获取的一个或多个ejb-jar文件中EJB部署到一个指定的环境。有时这个工作也由EJB提供者完成。这个环境包括特定的EJB服务器和容器。
部署者通常会使用EJB容器提供者提供的部署工具(如 WebLogic Server提供的weblogic.ejbc工具),来为EJB提供需要的外部资源并绑定这些资源,同时必须符合应用装配者定义的指令。
部署者的产品是定制到特定环境的EJB,这个产品只能被部署在那个特定的容其中。也就是说,EJB的部署是与服务器平台相关的。
部署者是应用环境的操作专家,负责与EJB部署相关的工作。如:他负责把应用装配者定义的安全角色和EJB部署环境中的用户组及账号对应起来,实现它们的映射。
EJB容器提供者提供的部署工具用来完成部署工作,这个过程分两个阶段:
(1)部署者首先生成附加类和接口,确保容器能管理EJB的运行。这些附加的类是和特定容器相关的。
(2)部署者完成EJB和附加类及附加接口的安装。
4. EJB服务器提供者
EJB服务器提供者,即生产EJB服务器的厂家。目前符合EJB规范的服务器产品有十几种,如 WebLogic Server,Websphere,iPlanet等。EJB服务器提供者是分布式事务、分布式对象和其它低级系统级服务的专家。一个典型的EJB服务器提供者可能是操作系统生产者、中间件生产者或数据库生产者。
目前EJB架构假定EJB服务器提供者和EJB容器提供者是同一个生产者,因此没有定义EJB服务器提供者的任何接口需求。
5. EJB容器提供者
容器提供者提供了:
(1)部署EJB需要的部署工具。
(2)EJB的运行环境。
从EJB的角度看,容器是EJB的运行环境。容器为EJB提供了事务管理、安全管理。分布式网络管理、资源管理等服务。
EJB架构定义的EJB容器提供者负责EJB容器和EJB服务器的实现。EJB规范没有定义EJB容器和服务器之间的接口,由厂家来实现EJB容器和服务器的划分。
容器提供者需要系统级的编程,容器提供者的重点是开发出可伸缩的、安全的、事务处理的容器,并把它集成到EJB服务器中。容器提供者把EJB和EJB服务器分离开,并在EJB和容器之间提供了简单、标准的API。这个API就是EJB的容器合约。
容器提供者通常会提供允许系统管理员监视和管理容器和运行在容器中的EJB的工具。
通常把具有EJB容器、EJB服务器和Web服务器功能的产品叫做应用服务器。它为开发企业级应用提供了一个完整的平台。
6. 管理器提供者
在EJB的使用和开发中,经常会遇到持久性的概念。所谓持久性,是指通过辅助的永久性的存储设备,如数据库或文件等,把Java对象的状态和对应的存储设备映射起来,当Java对象的状态发生改变时,存储的映射也随之改变。即使在Java对象消失后,存储设备中依旧保存着Java对象的状态。当这个Java对象重新实例后,它就会依然保持以前的状态,这就是Java对象的持久性。
在EJB规范中定义了具有持久性的EJB——实体EJB。根据对持久性管理方式的不同,又把实体 EJB分成容器管理持久性的 EJB(CMP EJB)和Bean管理持久性的EJB(BMP EJB)。
一般情况下,持久性管理器包含在容器管理器中。对于EJB提供者来说,不必了解它的细节。
对于容器管理持久性的实体EJB来说,持久性管理器负责安装在容器内的实体EJB的持久性管理。在部署阶段使用持久性管理器提供者的工具,可以生成代码,实现数据从实体EJB到数据库和应用程序的转换。
容器管理器管理实体Bean及其用到的对象的持久性和这些对象引用的完整性。容器管理器负责容器管理持久性实体EJB的finder方法和select方法的执行。
目前的EJB架构中没有完整定义容器和持久管理器间的接口,由厂家来自行定义。
7.管理者
系统管理者负责配置、企业级计算、包括EJB服务器和容器的网络设施的系统管理。同时,系统管理者监视部署在容器中的EJB的运行。
EJB架构没有为系统管理定义合约。系统管理通常使用EJB服务器和容器提供者提供监视管理工具来完成这些工作。
通常,应用服务器会提供系统管理的控制台工具(如 WebLogic Server中的 Console)。
3.3 EJB合约
这里的合约是指不同EJB角色合作的约定,也是不同角色的开发者开发的产品要遵守的约定。对于EJB提供者即开发者来说,要遵守客户端视图合约;对于EJB容器的开发者和使用者来说,要遵守组件和约。本节对这两个合约进行讨论。
在EJB开发过程中,这些合约的体现是EJB开发接口和一些EJB内部对象。
1. 客户端视图合约
是客户端与容器之间的合约。客户端视图合约为使用企业Beans作为组件开发应用程序提供一个统一的开发模式。这个统一的模型使使用高级的开发工具成为可能,并实现组件重用。企业Bean客户端视图是基于远程访问的,它允许本地和远程对象采用统一的方式进行访问。
一个企业Bean的客户端可能是部署在同一个或不同容器的另一个企业Bean。也可以是任何一个Java程序,如应用程序、Applet或Servlet。一个企业Bean的客户端视图也可以被映射到非Java客户端,如CORBA客户端。它不是由JavaTM编程语言写的。企业Bean提供者和容器提供者一同提供企业Bean的客户端视图。客户端视图包括:
·主程接口(Home Interface)
·远程接口(Remote Interface)
·对象识别(Object Identity)
·元数据接口(Metadata Interface)
·句柄(Handle)
主接口(Home Interface):定义创建、删除和查找同类 EJB对象的方法(即它们由同一个企业Bean实现)和主业务逻辑方法(即不是特定某个Bean实例的方法)。主接口由Bean提供者制订;容器创建一个类来实现主接口。主接口继承javax.ejb.EJBHome接口。
客户端通过标准的Java名称和目录接口(Java Naming and Directory Interface TM,JNDI)API定义企业Bean主接口。
EJB对象是通过远程接口(Remote Interface)来访问的。远程接口定义了客户端调用的业务逻辑方法。远程接口由Bean提供者制定;容器创建一个类来实现远程接口。远程接口继承了javax.ejb.EJBObject接口。javax.ejb.EJBObject接口定义了允许客户端访EJB对象标识和EJB对象创建一个持久性句柄的操作。
每个EJB对象在主域里存活,并有一个惟一的标识。对 Session Beans来说,容器负责为每个Session对象产生新的惟一标识。这个标识并没有暴露给客户端。然而,客户端可以测试两个对象引用是否指向同一个Session对象。对实体EJB来说,Bean提供者负责在Entity对象创建的时候提供一个主键;容器使用主键来在主域中标识实体对象。客户点可以通过javax.ejb.EJBObject接口获取一个实体对象的主键。客户端也可以测试两个对象引用是否指向同一个实体对象。
客户端也可以获取企业Bean的元数据接口。客户端使用元数据接口主要用在执行企业Bean的动态调用上。(提供客户端视图的类不可用的时候需要动态调用)。
消息驱动Beans没有Home和Remote接口,因此它没有客户端视图。客户端可以通过标准JNDI API定位发到消息驱动Bean的消息所在的JMS目标。
2. 组件合约
这部分描述企业Bean和它的容器之间的合约,以及在容器管理持久性的企业Bean情况下,企业Bean和它的持久管理器之间的合约。主要的合约如下(部分):
·需要Bean提供者实现企业Bean类中的业务方法。需要容器提供者提供客户端调用这些方法的代理。
·对于消息驱动Beans来说,需要Bean提供者实现企业Bean类中的onMessage方法。需要容器提供者调用这些方法。
·如果Bean是实体并且是Bean管理持久性(BMP)的,需要Bean提供者实现ejbCreate方法ejbPostCreate方法、ejbRemove方法和ejbFind方法。需要容器提供者在EJB对象的创建、删除和查询的过程中调用这些方法。
·对于容器管理的持久性,需要Bean提供者为持久属性提供抽象的访问方法和一个实体与容器管理持久性的关系。需要持久管理提供者提供这些方法的实现。
·需要Bean提供者提供持久性管理器实现的关系描述。
·需要Bean提供者定义企业Bean的主接口和远程接口,如果是实体Bean或Session Bean,需要Container提供者提供实现这些接口的类。
·对会话来说,需要Bean提供实现javax.ejb.SessionBean接口或在javax.ejb.SessionSynchronization接口中定义的容器回调。需要容器管理者在适当的时候调用这些回调。
·对消息驱动Beans来说,需要Bean提供者实现定义在接口javax.ejb.MessageDrivenBean中的容器回调。
·对实体EJB来说,需要Bean提供者实现定义在javax.ejb.EntityBean中的容器回调。需要容器在适当的时候调用这些回调。
·需要持久管理器提供者实现实体Beans的持久性。
·需要容器提供者为会话bean实例提供javax.ejb.SessionContext接口,为实体bean实例提供javax.ejb.EntityContext接口,为消息驱动bean实例提供javax.ejb.MessageDrivenContext接口。上下文接口允许实例获取容器的信息。
·需要容器为Bean实例提供JNDI上下文,它包含企业Bean的环境信息。
·需要容器为企业Bean实例管理事务、安全和异常。
·需要Bean提供者避免程序影响企业Bean实例的容器运行时管理。
3. ejb-jar文件
一个ejb-jar文件具有标准的格式。EJB工具用它来作为描述性的语言打包企业Beans。ejb-jar文件用来执行程序的装配和部署。
ejb-jar文件包括:
·企业Beans的Java类文件和它们的远程和主接口。
·XML部署描述符。部署描述符提供关于在ejb-jar文件中的企业Beans的结构和装配信息。
4. 合约总结
如图3-2描述了EJB的合约。
注意 图3-2只显示远程客户端运行在Container外的情况,客户端视图API也可以用在同一个容器中的企业Beans。
3.4 会话、实体和消息驱动Bean对象
EJB架构定义了三种类型的企业Bean对象:
·会话对象(Session Obect)
·实体对象(Entity Obect)
·消息驱动对象(Message-Driven Object)
1. 会话对象(Session)
一个典型的会话对象具有如下特征:
·由一个客户端执行。
·自动事务感知。
·在一个潜在的数据库中更新共享数据。
·不直接表示数据库中的共享数据,虽然它可以访问和更新这些数据。
·相对来说是短命的。
·当EJB容器停止后被清除掉。客户只能重新建立新的对象来继续计算。
一个典型的EJB Containe提供一个灵活的运行环境来并发的执行大量的会话对象。
会话Beans是有状态的。同时EJB规范也支持无状态会话Bean作为一个特殊的情况。有状态(正常)会话Beans和无状态会话Bean的API有很小的差别。
2. 实体对象(Entity)
一个典型的实体对象有如下特征;
·提供一个数据库的数据视图。
·允许多个用户共享访问。
·存活时间长(和数据库中的数据一样)。
·实体,主键和远程引用可以在EJB容器停止后存活。如果实体的状态被事务更新,同时容器停止,实体的状态自动地重新置为最后一次触发事务的状态。停止对于客户端来说不是完全透明的,在它调用一个实体容器崩溃的时候,客户端可能会收到一个异常。
特殊的EJB容器和服务器为多个并发的实体对象提供一个可变的运行时环境。
3. 消息驱动对象
一个典型的消息驱动对象具有如下特征:
·收到某个客户端消息时执行。
·自动事务感知。
·自动更新共享数据。
·不直接代表数据库中的共享数据,虽然它可以访问和更新这些数据。
·生命短。
·无状态。
·EJB容器崩溃时被删除。容器不得不重新建立新的消息驱动对象来继续计算。
一个典型的EJB容器提供一个灵活的运行环境来同时执行多个消息驱动对象。
3.4 会话、实体和消息驱动Bean对象
EJB架构定义了三种类型的企业Bean对象:
·会话对象(Session Obect)
·实体对象(Entity Obect)
·消息驱动对象(Message-Driven Object)
1. 会话对象(Session)
一个典型的会话对象具有如下特征:
·由一个客户端执行。
·自动事务感知。
·在一个潜在的数据库中更新共享数据。
·不直接表示数据库中的共享数据,虽然它可以访问和更新这些数据。
·相对来说是短命的。
·当EJB容器停止后被清除掉。客户只能重新建立新的对象来继续计算。
一个典型的EJB Containe提供一个灵活的运行环境来并发的执行大量的会话对象。
会话Beans是有状态的。同时EJB规范也支持无状态会话Bean作为一个特殊的情况。有状态(正常)会话Beans和无状态会话Bean的API有很小的差别。
2. 实体对象(Entity)
一个典型的实体对象有如下特征;
·提供一个数据库的数据视图。
·允许多个用户共享访问。
·存活时间长(和数据库中的数据一样)。
·实体,主键和远程引用可以在EJB容器停止后存活。如果实体的状态被事务更新,同时容器停止,实体的状态自动地重新置为最后一次触发事务的状态。停止对于客户端来说不是完全透明的,在它调用一个实体容器崩溃的时候,客户端可能会收到一个异常。
特殊的EJB容器和服务器为多个并发的实体对象提供一个可变的运行时环境。
3. 消息驱动对象
一个典型的消息驱动对象具有如下特征:
·收到某个客户端消息时执行。
·自动事务感知。
·自动更新共享数据。
·不直接代表数据库中的共享数据,虽然它可以访问和更新这些数据。
·生命短。
·无状态。
·EJB容器崩溃时被删除。容器不得不重新建立新的消息驱动对象来继续计算。
一个典型的EJB容器提供一个灵活的运行环境来同时执行多个消息驱动对象。
3.4 会话、实体和消息驱动Bean对象
EJB架构定义了三种类型的企业Bean对象:
·会话对象(Session Obect)
·实体对象(Entity Obect)
·消息驱动对象(Message-Driven Object)
1. 会话对象(Session)
一个典型的会话对象具有如下特征:
·由一个客户端执行。
·自动事务感知。
·在一个潜在的数据库中更新共享数据。
·不直接表示数据库中的共享数据,虽然它可以访问和更新这些数据。
·相对来说是短命的。
·当EJB容器停止后被清除掉。客户只能重新建立新的对象来继续计算。
一个典型的EJB Containe提供一个灵活的运行环境来并发的执行大量的会话对象。
会话Beans是有状态的。同时EJB规范也支持无状态会话Bean作为一个特殊的情况。有状态(正常)会话Beans和无状态会话Bean的API有很小的差别。
2. 实体对象(Entity)
一个典型的实体对象有如下特征;
·提供一个数据库的数据视图。
·允许多个用户共享访问。
·存活时间长(和数据库中的数据一样)。
·实体,主键和远程引用可以在EJB容器停止后存活。如果实体的状态被事务更新,同时容器停止,实体的状态自动地重新置为最后一次触发事务的状态。停止对于客户端来说不是完全透明的,在它调用一个实体容器崩溃的时候,客户端可能会收到一个异常。
特殊的EJB容器和服务器为多个并发的实体对象提供一个可变的运行时环境。
3. 消息驱动对象
一个典型的消息驱动对象具有如下特征:
·收到某个客户端消息时执行。
·自动事务感知。
·自动更新共享数据。
·不直接代表数据库中的共享数据,虽然它可以访问和更新这些数据。
·生命短。
·无状态。
·EJB容器崩溃时被删除。容器不得不重新建立新的消息驱动对象来继续计算。
一个典型的EJB容器提供一个灵活的运行环境来同时执行多个消息驱动对象。
3.5 CORBA协议的标准映射
为了实现不同系统的EJB环境间的协作,EJB 2.0规范需要会话Beans和实体Beans的J2EE客户调用端支持基于CORBA/IIOP协议兼容的实现。
3.6 本章小结
对于本章阐述的概念,读者不可能在看过一次后完全领会。本书后面几章提供了大量的EJB应用的实例,读者在实际操作完这些例子后再重新理解这些概念会取得更好的效果。
下一章讨论会话EJB的特征、编程模型和实例开发。