??xml version="1.0" encoding="utf-8" standalone="yes"?>
一、两U引用类?span lang="EN-US">
Z从其?span lang="EN-US">EJBlg讉K某个BeanQ容器提供了一U特D的机制。这U机制允怸?span lang="EN-US">Bean提供者通过UCؓEJB引用的“逻辑名字”引用另一?span lang="EN-US">EJB?span lang="EN-US">Home?span lang="EN-US">EJB容器利用应用的部|描q器?span lang="EN-US">EJB构造环境,而这些引用在部v描述器中作ؓҎ的项目声明。在部v描述器中Q部|者把lg代码中要用到?span lang="EN-US">EJB引用l定到其他被引用EJB?span lang="EN-US">Home?span lang="EN-US">
如前所qͼ?span lang="EN-US">EJB 2.0规范出现之前Q在一?span lang="EN-US">EJB中引用其?span lang="EN-US">Bean只有一U方法,即通过q程接口Q它要求q行跨越|络的远E过E调用。如果某个事务由多个Bean协作完成Q通过|络q行多个对象的汇集和释放是一相当繁重的工作?span lang="EN-US">
EJB 2.0规范新增了一U本地接口类型,允许在同一容器之内?span lang="EN-US">Bean直接互相引用Q避免了q程接口的网l开销。本地接口是一U标准的Java接口Q而不是从RMIl承得到?span lang="EN-US">EJBlg的定义可以包含本地接口或q程接口Q或者两者都定义?span lang="EN-US">
本地引用的指定方式和传统的远E引用一P卛_部v描述器中指定。事实上Q本地引用的部v描述元素与远E引用的描述元素完全对应?span lang="EN-US">
下面的代码片断是一个典型的q程引用Q?span lang="EN-US">
Product
ejb/Product
Entity
com.xyz.widgets.ProductHome
com.xyz.widgets.Product
../products/product.jar#Product
下面的代码片断是同一Bean的本地引用:
Product
ejb/Product
Entity
com.xyz.widgets.ProductHome
com.xyz.widgets.Product
../products/product.jar#Product
下表要说明了各个元素的用途:
二、创建本地接口,通过本地接口讉KEJB
要把一个现有的q程接口改ؓ本地接口Q有三个地方必须修改Q部|描q器Q?span lang="EN-US">Bean的接口,以及?span lang="EN-US">EJB的调用。前面我们介l了如何通过部v描述器指定一个本地引用,现在我们要把q程接口转换成本地接口,然后修改JNDI查找调用Q让它用新的本地接口?span lang="EN-US">
?span lang="EN-US"> Home接口
指定Home接口Ӟ现在必须导入的是?span lang="EN-US">javax.ejb.EJBLocalHome”,而不是?span lang="EN-US">javax.ejb.EJBHome”。接口的声明也必L变,让它从?span lang="EN-US">EJBLocalHome”(一个标?span lang="EN-US">Java接口Q承,而不是从?span lang="EN-US">EJBHome”(一?span lang="EN-US">RMI接口Qѝ同Ӟ从该接口定义的方法中唯一应该抛出的异常是javax.ejb.CreateExceptionQ?span lang="EN-US">java.rmi.RemoteException异常则不再必要?span lang="EN-US">
?本地接口
指定本地接口Ӟ现在必须导入?span lang="EN-US">javax.ejb.EJBLocalObject”,而不是?span lang="EN-US">javax.ejb.EJBObject”。接口声明也必须改变Q让它从?span lang="EN-US">EJBLocalObject”(一个本地接口)l承Q而不是从?span lang="EN-US">EJBObject”(一?span lang="EN-US">RMI接口Qѝ?span lang="EN-US">
?执行调用
创徏好接口、设|好部v描述器之后,剩下的工作就是执?span lang="EN-US">JNDI调用Q查扑֯其他EJB的引用。调?span lang="EN-US">Bean的远E接口时Q?span lang="EN-US">javax.rmi.PortableRemoteObject的?span lang="EN-US">narrow()”方法汇集经q?span lang="EN-US">RMI的调用。对于本地引用,q种开销׃再必要,q时只需单地q行JNDI查找q进行适当的类型定型。下面是一个例子:
home = (ProductHome) initCtx.lookup("java:comp/env/ejb/Product");
它不仅提高了效率Q而且代码也比用来获取q程接口的代码更直观易懂?span lang="EN-US">
本地接口使得处于同一容器内的两个EJBlg能够更高效地q行通信。对于实?span lang="EN-US">Bean的应用来_q种技术尤其有用,因ؓ与客L序直接访问实?span lang="EN-US">Bean相比Q在实践中,通过会话Bean讉K实体Bean得到了更q泛的认可?span lang="EN-US">
在现今的技术条件下Q何时以及是否?span lang="EN-US"> EJB lg是方案小l面临的一个十分烦人的问题。ؓ帮助你做出正决定,我们准备了一些问题,以供你在考虑从其它技术{Ud EJB lgQ或者考虑一个可能?span lang="EN-US"> EJB lg的新Ҏ时作为判断依据。我们还比较两个用了 EJB lg的方案,q将看到它们是如何被正确或错误地应用于实际的?span lang="EN-US">
什么是 EJB lgQ?span lang="EN-US">EJB lg是ؓ企业U应用设计的 java lg模型?span lang="EN-US">
EJB lg是基于标准分布式对象技术?span lang="EN-US">CORBA ?span lang="EN-US"> RMI 的服务器?span lang="EN-US"> java lg?span lang="EN-US">EJB lgL分布式的Q这是它们与标准 JavaBeans lg最Ҏ的区别?span lang="EN-US">
EJB lg提供了应用的商务逻辑部分。由于它们不涉及表示层的问题Q因此必M其它的显C技?span lang="EN-US">(?span lang="EN-US"> servlets)Q服务于 HTML 客户端的 JSP 技术,或者用了诸如 AWT?span lang="EN-US">Swing 技术的 java 应用一起用?span lang="EN-US">
实现?span lang="EN-US"> EJB 规范的应用服务器提供了可以解军_全性、资源共享、持l运行、ƈ行处理、事务完整性等复杂问题的服务,从而简化了商业应用pȝ?span lang="EN-US">
Sun 公司制定?span lang="EN-US"> EJB lg模型要求 EJB lgq行?span lang="EN-US"> EJB 服务?span lang="EN-US">(通常UCؓ应用服务?span lang="EN-US">)的环境下。我们的CZ中用了高?span lang="EN-US"> WebSphere 应用服务器,但所讨论的功能适用于大多数 EJB 服务器?span lang="EN-US">
需要考虑的技术问?span lang="EN-US">
当你在决?span lang="EN-US"> EJB lg是否为适合你的实际情况的合适技术时Q不妨先考虑几个问题。如果你Ҏ有这些问题的回答都是肯定的话Q那?span lang="EN-US"> EJB lg是你可以采用的合适技术。反之的话,别的技术可能更适合?span lang="EN-US">
你需要将商务逻辑lg与面向外界的 Internet 隔离开吗?
许多公司认ؓ他们的应用YӞ特别是构成商务逻辑的一些标准和数据l构Q是极ؓ重要的公司胦?span lang="EN-US">(例如Q公司所拥有的分析应用工h成了股票交易|站的一部分)。允许外问这些属于公司资产的原码和目标码对公司产生极大的危実뀂因此,q些公司十分需要将商务逻辑|于一套安全防火墙后面(通常UCؓ无戒备区Q也U?span lang="EN-US"> DMZ)?span lang="EN-US">
在这U情况下Q分布式对象lg体系l构(例如 EJB 技?span lang="EN-US">)允许你将有h值的公司资隔离?span lang="EN-US"> DMZ 以内Q同时表C层代码可以讉K DMZ 内的 EJB 服务器。下图描qCq种分布式解x案:
防火墙内部的 EJB
q里我们假设表示层逻辑不如后台的商务逻辑重要。如果不是这P那么q种Ҏ的安全性就要下降,整个pȝ可能都需要置?span lang="EN-US"> DMZ 之内。如果整个应用必?span lang="EN-US">(或者能?span lang="EN-US">)|于W二层防火墙后面Q那么选择其它技?span lang="EN-US">(如通过 Java Servlets 发出 JDBC h来直接访问数据库)显得更合理?span lang="EN-US">
q种解决Ҏ也有一些效率方面的~陷。例如在安装 WebSphere Ӟ如果你将客户?span lang="EN-US">(servlets ?span lang="EN-US"> JSP文g)与图C的位于另一?span lang="EN-US"> java 虚拟?span lang="EN-US">(JVM)中的 EJB lg分隔开Q这U选择降低整体性能。与客户端和 EJB lg位于同一?span lang="EN-US"> JVM 中的情况相比Q这U方式下每一个需要经q防火墙的请求都增?span lang="EN-US">20%的耗时?span lang="EN-US">
你需要不止一U类型的客户端访问共享数据吗Q?span lang="EN-US">
通常Q一个应用会有多U类型、需要访问相同信息的客户端。例如,一个应用可能会有供外部客户讉K的基?span lang="EN-US"> web ?span lang="EN-US"> HTML 前端Q以及供内部人员使用的更完整的应用前端。通常Q这个问题是通过为同一应用~写两个׃n相同数据?span lang="EN-US">(数据库表)的版本来解决的。但是,q种Ҏ效率不高Q无论是从编E时间还是从同时发生多个数据库锁定时数据库的利用率来说?span lang="EN-US">
EJB 技术的解决Ҏ是将׃n数据和商务逻辑集成C?span lang="EN-US"> EJB lg中,以供不同cd的客L(?span lang="EN-US"> servlet/HTML ?span lang="EN-US"> application)讉K?span lang="EN-US">EJB lg控制着对后台数据的讉KQƈ理着当前事务以及数据库的内部锁定。通过去除应用中的重复代码Q减编写数据库控制逻辑的工作,q种Ҏ降低了ȝ~程量?span lang="EN-US">
在这个领域还有其它一些解x?span lang="EN-US">--比如Q?span lang="EN-US">java 应用可以通过 HTTP 讉K java servletsQ同时浏览器也可以通过 HTTP 讉K java servlets。这些解x案的问题在于Q如?span lang="EN-US"> servlet 是用来在览器中昄信息的,它就必须包含一些表C层逻辑Q这些表C层逻辑对于向另一个程序传递信息来说是多余的。因此,你最l不得不采用两套部分重复?span lang="EN-US"> servlets 来处理两U情c此外,HTTP 不是E序间通讯的效率最高的协议。你必须设计能通过 HTTP 道q行E序间信息传递的数据格式--q通常或者是Z文本的格式,比如 XMLQ由接收端进行解析,由发送端生成Q,或者是Z对象的格式,比如 java 序列化。两U格式都需要大量的~程工作Q它们都不如本地?span lang="EN-US"> IIOP 速度快?span lang="EN-US">
你是否需要对׃n数据同时q行d写操作?
通常Q?span lang="EN-US">"胖客L"解决Ҏ要求应用在数据库U别上管理对׃n数据的访问。其l果是:处理数据库锁定与同步的方案非常复杂,若不考虑数据库锁定与同步问题又会失去数据的完整性?span lang="EN-US">
EJB 技术能自动处理q些复杂的共享数据同步问题。正如前面提到的那样Q?span lang="EN-US">EJB lg控制着对后台数据的讉KQƈ理着当前事务和数据库的内部锁定。这不仅省去了编写数据库控制逻辑的工作量Q同时也保证了数据的一致性与正确性,从而降低了ȝ~程量?span lang="EN-US">
你需要访问具备事务处理功能的多个异构数据源吗Q?span lang="EN-US">
许多应用需要访问多个数据源。例如,一个应用程序可能既要访问来自中间层?span lang="EN-US"> Oracle 数据库,又要通过中间?span lang="EN-US">(?span lang="EN-US"> MQSeries)讉K CICS?span lang="EN-US">IMS {大型主机系l。问题的关键是一些应用要求这U访问是完全事务化的Qƈ且数据完整性在不同数据源间也能得到保证。例如,某个应用可能要求在处理用L订购信息Ӟ既要?span lang="EN-US"> Oracle 数据库中存储详细的订购信息,同时又通过 MQSeries ?span lang="EN-US"> CICS pȝ中存储一份出货订单。无论是数据库更新或?span lang="EN-US"> MQ 队列产生错误Q整个事务都应被取消?span lang="EN-US">
q去Q构Lpȝ的唯一选择是采用事务监视器Q例?span lang="EN-US"> Encina?span lang="EN-US">CICS?span lang="EN-US">TuxedoQ它们用非标准接口q要用 COBOL?span lang="EN-US">C?span lang="EN-US">C++ {语aq行开发。例如,高?span lang="EN-US"> WebSphere 中的 EJB 容器支持多个q发的事务,具备在多?span lang="EN-US"> DB2 数据源间q行完整的事务提交及事务取消的能力,q些都是在一个完全支持二状态事务提交的环境中进行的。目前,WebSphere 对其它数据源(?span lang="EN-US"> Oracle, MQSeries ?span lang="EN-US"> CICS)只支持单状态的事务提交。企业版 WebSphere 中的 EJB 容器能对更多的数据源支持二状态的事务提交?span lang="EN-US">
大多数容器正在支持各U数据源下的二状态事务提交方面不断完善。随着旉的推U,我们在q一领域看到不断的进步?span lang="EN-US">
你需要能?span lang="EN-US"> HTML 文档?span lang="EN-US">servlets?span lang="EN-US">JSP 文g、客Ld安全性无~集成的ҎU对象安全性吗Q?span lang="EN-US">
某些cd的应用由于其安全性限Ӟ使得以前它们很难通过 java 应用来实现。例如,某些保险业的应用E序Z满理规定的要求,必须限制对客h据的讉K。直?span lang="EN-US"> EJB 技术出现后Q才能够限制特定用户讉K某个对象或方法。在q之前,可实施的办法只有Q在数据库别上限制讉KQƈ捕获?span lang="EN-US"> JDBC 层次上抛出的错误Q或者通过客户安全密码在应用层上限制访问?span lang="EN-US">
EJB 技术可以在M EJB lg或方法上实施ҎU的安全{略。创建的用户和用L可以被授予或止对Q?span lang="EN-US"> EJB lg或方法的操作权。在 WebSphere 中,用户l可以被授予或禁止对 web 资源(servlets, JSP 文g?span lang="EN-US"> HTML 面)的访问权Q用L ID 可以通过底层的安全机制被安全C web 资源传递到 EJB lg?span lang="EN-US">
体系l构是否有标准化、轻量化、组件化的需要呢Q?span lang="EN-US">
对于许多有远见的公司来说Q关键问题是要实现^台、销售商和应用服务器讑֤间的怺独立。符合工业标准的 EJB lg体系l构有助于实现这些目标。ؓ WebSphere 开发的 EJB lg通常可以发布到其它类型的应用服务器上使用Q反之亦然。尽这一目标未完全实现Q但它已成ؓ许多客户选择的战略发展方向。从短期看,利用一些可能优于标准化的特性会更方ѝ更q速,但从长远看标准化h最大的好处?span lang="EN-US">
你也应当考虑到越来越多的可选工具和 EJB 标准的优化实现手D,q些都是你无法从本地理对象框架中获得的。由于大多数公司q不从事中间件业务,注意力集中在与你的业务更直接相关的zd上会更有效?span lang="EN-US">
你需要多个服务器来满系l的吞吐量和有效性需要吗Q?span lang="EN-US">
胖客Lpȝ昄不能适应 web pȝ可能拥有的成千上万个用户。Y件发布方面的问题也要求给胖客L减肥?span lang="EN-US">Web 站点?span lang="EN-US">24时不间断运行特点也使得旉成ؓ关键问题。但q不是每个h都需?span lang="EN-US">24时不间断运行,q能同时处理上万个用Lpȝ。你应当能设计这LpȝQ在不增加开发和标准化难度的前提下,实现pȝ的~性?span lang="EN-US">
因此Q你要设法得编写的商务逻辑可以q行伸羃来满些需要?span lang="EN-US">EJB 技术ؓ构徏q种h高~性、高利用率的pȝ提供了骨架。例如,WebSphere 通过以下一些特性帮助开发者构cȝl。这些特性也适用于其它的 EJB 服务器:
对象~存与共享?span lang="EN-US">WebSphere 自动在服务器层面上共享无状态会?span lang="EN-US"> EJB lgQ从而减了用于创徏对象和回收碎片的旉。这得更多的处理旉周期可以分配l真正的实际工作?span lang="EN-US">
服务器端的工作量优化?span lang="EN-US">WebSphere q?span lang="EN-US"> EJB 服务器具备群理的特炏V在 WebSphere 应用服务器上Q你可以创徏跨越多个节点的服务器l。除此之外,你可以创建模?span lang="EN-US">(服务器的抽象表述)Qƈ把它们克隆到多个 JVM 中。你可以克隆的模型配置成运行于l内的Q何一台服务器上。另外,一个服务器的多个克隆模型也能运行与一台机子上Q充分利用了多处理器的结构特炏V同P你也可以把所有克隆的模型作ؓ一个组来管理。这提高了可靠性,避免了个别地Ҏ障时对应用服务器的破坏?span lang="EN-US">
通过克隆可支持自动故障恢复。由于有几个克隆的服务器可以用来处理hQ故障不太可能破坏系l的吞吐量和可靠性。由于多个节点运行相同的服务Q一台整机的故障׃会生灾难性的后果?span lang="EN-US">
所有这些特性都不需要对pȝq行Ҏ的编E。利用这U可伸羃性也无需改动服务器端的代码?span lang="EN-US">
WebSphere 支持其它服务器端 java 技?span lang="EN-US">(?span lang="EN-US"> java servletsQ?span lang="EN-US">JSP文g)的发布、克隆和自动故障恢复。但是,q些更面向表C层的技术与其说?span lang="EN-US"> EJB lg的竞争对手,不如说是对其的补充。当M旉和可伸羃性是问题的关键时Q整体解x案中应包?span lang="EN-US"> EJB lg?span lang="EN-US">
关于两个Ҏ的描qͼ或者说是关于正?span lang="EN-US"> EJB lg的描q?span lang="EN-US">
现在你已l了解了一些评C个应用是否适合使用 EJB 技术的办法Q下面我们来比较两个使用?span lang="EN-US"> EJB lg的应用,看看 EJB 技术究竟是帮助q是ȝ了开发者达到目标。在一个例子中 EJB lg的正用得代码更z、更易懂。在另一个例子中Q?span lang="EN-US"> EJB lg使得pȝq于复杂Q性能也不好?span lang="EN-US">
q两个应用都是综合了多个其它应用的例子,而不是来自于某个单一的公司或Ҏ组?span lang="EN-US">
一个?span lang="EN-US"> EJB 技术失败的例子
作ؓ一个被授权评估新技术的高技术小l的成员Q某个方案小l最初设计了q个Ҏ。该Ҏh如下体系l构(每个Ҏ代表q行于各自硬件上的不同程?span lang="EN-US">)Q?span lang="EN-US">
不可取的 EJB 体系l构
该体pȝ构的一些具体设计?span lang="EN-US"> EJB lg的用不如它初看h那么有吸引力Q?span lang="EN-US">
应用的主体部分是信息的显C,q部分由 java servlets 实现?span lang="EN-US">EJB lg只用来获取、更新数据?span lang="EN-US">
Ҏ组在后C机的事务处理中用的数据q接不包括遵从扩充体pȝ?span lang="EN-US">(XA)标准的数据源。事务不能被成批取消或提交,Ҏ个主机的讉K都是一个独立的h?span lang="EN-US">
׃不能区分用户是来?span lang="EN-US"> web q是来自后台LQ?span lang="EN-US">EJB 技术的安全Ҏ在此没有得到利用?span lang="EN-US">
servlet ?span lang="EN-US"> EJB lg的每一ơ访问都是一个网l请求。组件的探测Ҏ?span lang="EN-US"> ejbLoad() Ҏ的内部逻辑执行了真正的LhQ但q之?span lang="EN-US"> EJB lg仅仅q行数据~存Q直C务提交后才由 ejbStore() Ҏ信息回传给L。直C务提交前的每一ơ数据访问和更新都导致了大量的网l开销?span lang="EN-US">
该方案小l仅仅把 EJB lg用作L数据?span lang="EN-US"> servlets 间的数据映射机制Q这不是 EJB 技术的有效使用Ҏ。本例中的应用没有利用以下一些特性:
EJB lg的事务处理特?span lang="EN-US">
EJB lg的方法安全?span lang="EN-US">
EJB lg的~性与分布式特?span lang="EN-US">(该方案小l仅使用了一?span lang="EN-US"> EJB 服务?span lang="EN-US">)
多种cd客户端间的商务逻辑׃n
具备容器理持久?span lang="EN-US">(CMP)?span lang="EN-US"> EJB lg的自动数据映功?span lang="EN-US">
如果直接由和 java servlets 处于同一 JVM 中的 JavaBeans lg来实现数据映功能,pȝ的速度比使用 EJB lg快得多,同时避免了大量的|络开销。该pȝq变得不必要的复?span lang="EN-US">(因ؓ需要本地和q程接口Q以及分布代?span lang="EN-US">)。事实上Q该Ҏ后来被废弃ƈ以不使用 EJB lg的方式进行了重新设计Q其中的数据映射׃套被 servlets 使用的标?span lang="EN-US"> JavaBeans lg实现。这使得最后的pȝ变得更简单、更快速?span lang="EN-US">
一个成功?span lang="EN-US">EJB技术的例子
一个金融机构的Ҏ组设计了这套方案,最初用了 java ?span lang="EN-US"> RMI 技术。其pȝ体系l构如下Q?span lang="EN-US">
RMI服务器体pȝ?span lang="EN-US">
除了多种cd的客LQ方案小l还在系l内构徏了以下两个框架单元,在本图中未画出来Q?span lang="EN-US">
一个数据库映射层,通过 RMI 服务器上?span lang="EN-US"> JDBC 其 Oracle 数据表映成 java c,或者反q来?span lang="EN-US">
一个用户安全框架单元,用于验证来自览器或应用客户端的用户Qƈq而决定用h否有权进?span lang="EN-US"> RMI 和数据库h?span lang="EN-US">
׃他们的应用需求与 EJB 技术的目标紧密相连Q该Ҏ组得以很快其设计Ҏ转变Z下体pȝ构:
新的 EJB 体系l构
通过使用容器理持久?span lang="EN-US">(CMP)Q?span lang="EN-US">EJB lg使得Ҏ组可以抛弃数据库映框Ӟ转而利?span lang="EN-US"> WebSphere ?VisualAge for Java 中完整高效的实现机制。通过利用 EJB 技术的安全性,Ҏ组得以在应用中保留ҎU安全性的同时Q抛弃了他们的用户安全框架。结果,׃需要维护的代码量减了Q他们的应用变得更ؓ单?span lang="EN-US">
单地_该应用的以下特点使得它适合使用 EJB 技术:
h׃n相同商务逻辑的多U类型客L
使用了事务处?span lang="EN-US">
需要通过 CMP lg来实C对象有关的映?span lang="EN-US">
需要方法的安全?span lang="EN-US">
׃pȝ的设计目标是通过使用与实体同时发布的会话U?span lang="EN-US"> EJB lg来实现最的|络量Q该pȝ最l的体系l构很好C用了 EJB lg。对于前一U体pȝ构,׃客户端需要发出大量的hQ很可能会增加网l负担,另外׃要求客户端进行事务的启动、提交、取消,使得pȝ复杂化?span lang="EN-US">
安装EJBq行和开发环?/span>
EJB必须要在EJB容器内执行。所以,我们必须安装一个符?span lang="EN-US">J2EE标准?span lang="EN-US">EJB容器。ؓ了帮助我们部|自qEJBQ我们还需要一个部|工兗来?span lang="EN-US">Sun的、对J2EE的参考实现包含了一?span lang="EN-US">EJB容器和一?span lang="EN-US">EJB部v工具。这?span lang="EN-US">J2EE参考实现能够在Sun发布?span lang="EN-US">J2EE开发工具包里找到?span lang="EN-US">
J2EE开发包要依?span lang="EN-US">Java 2 SDK、标准版Q?span lang="EN-US">Standard EditionQ?span lang="EN-US">J2SEQ的开发包Q所以你也需要把它下载下来。你需?span lang="EN-US">J2SE SDK 来运行参照实现的J2EE服务器,q创建和q行EJB应用E序?span lang="EN-US">
一旦你下蝲了开发包Q你p安装它们Qƈ为每个开发包选择理想的位|。你要先定义一个叫?span lang="EN-US">JAVA_HOME的环境变量,q将它指?span lang="EN-US">J2SE开发包的安装目录。然后,定义一个叫?span lang="EN-US">J2EE_HOME的环境变量,q把它指?span lang="EN-US">J2EE开发包的安装目录?span lang="EN-US">
现在你就准备好开始编写你?span lang="EN-US">EJB了?span lang="EN-US">
~写一个简单会?span lang="EN-US">EJB
开发一?span lang="EN-US">EJB所涉及的大多数步骤和概念和我们开发传l的Java对象Q?span lang="EN-US">plain-old Java objectQ?span lang="EN-US">POJOQ所使用的是相同的,只有数的不同之处。下面就是开发和部vEJB的一个基本步骤:
1. Z?span lang="EN-US">EJB~写cd接口?span lang="EN-US">
2. Z?span lang="EN-US">EJB~写部v描述W?span lang="EN-US">
3. ?span lang="EN-US">EJB和相兌的文件打包进一?span lang="EN-US">jar文g?span lang="EN-US">
4. 部vEJB?span lang="EN-US">
会话bean有两U不同的cd。在我们开始编写代码之前,让我们来看看它们之间的相同之处和不同之处?span lang="EN-US">
状态会?span lang="EN-US">EJB概述
状态会?span lang="EN-US">EJB会在单个会话期间l持一U和客户端的对话状态。这pC状态会?span lang="EN-US">EJB能够在单个会话期_l持从一个客L跨越多个调用的实例变量?span lang="EN-US">
一旦客L完成了同EJB的交互操作,而且EJBҎ删除?span lang="EN-US">EJBQ那?span lang="EN-US">EJB的会话就会结束,用于EJB的所有状态数据都会被删除?span lang="EN-US">
无状态会?span lang="EN-US">EJB概述
无状态会?span lang="EN-US">EJB不会为每个单独的客户端都l持一个对话状态。对无状态会?span lang="EN-US">EJB的每ơ调用,都应该被当作是对一个全新的对象实例的请求。因ZQ何实例-变量状态都会在调用之间丢失?span lang="EN-US">
无状态会?span lang="EN-US">EJB不会?span lang="EN-US">EJB容器保存到第二存储地里,所以程序员必须要知道:每个客户端的每次调用之间的所有数据都是瞬时的。无状态会?span lang="EN-US">EJB的瞬时特性允?span lang="EN-US">EJB容器重复使用EJB实例Q因此常怼优化EJB的性能?span lang="EN-US">
会话Bean之间的关p?/span>
?span lang="EN-US">A说明?span lang="EN-US">EJB客户端?span lang="EN-US">EJB容器和几个会?span lang="EN-US">EJB之间的关pR?span lang="EN-US">
会话EJB包括臛_三个强制c/接口。第一个强制类Q接口是Component接口?span lang="EN-US">Component接口定义了一些对EJB来说是可视的商业ҎQ它必须扩展javax.ejb.EJBObject?span lang="EN-US">
q里我们会D个例子,实现一个非常简单的无状态会?span lang="EN-US">EJBQ它会在一个叫?span lang="EN-US">getBalance的方法里q回帐目l算。我?span lang="EN-US">Component接口的代码如下:
package com.jeffhanson.ejb;
public interface Account extends javax.ejb.EJBObject, java.rmi.Remote
{
public String getBalance() throws java.rmi.RemoteException;
}
W二个强制类Q接口是Home接口?span lang="EN-US">Home接口?span lang="EN-US">EJB客户端用来获取对Bean的组件接口的参照Q它必须扩展javax.ejb.EJBHome。我?span lang="EN-US">Home接口的代码如下:
package com.jeffhanson.ejb;
public interface AccountHome extends javax.ejb.EJBHome
{
public Account create() throws javax.ejb.CreateException,
java.rmi.RemoteException;
}
W三个强制类Q接口是Enterprise BeancR?span lang="EN-US">Enterprise BeancMؓComponent接口?span lang="EN-US">Home接口提供实现。用于会?span lang="EN-US">EJB?span lang="EN-US">Enterprise Beancd要实现javax.ejb.SessionBean接口。我?span lang="EN-US">Enterprise Beancȝ代码如下Q?span lang="EN-US">
package com.jeffhanson.ejb;
public class AccountBean
implements javax.ejb.SessionBean
{
private javax.ejb.SessionContextctx;
public void ejbActivate() {}
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbPassivate() {}
public void setSessionContext(javax.ejb.SessionContextctx)
{
this.ctx = ctx;
}
// business method
public String getBalance()
throws java.rmi.RemoteException
{
String balance = dataObj.getAccountBalance();
return(balance);
}
}
l束?/span>
EJB的全U是Enterprise Java bean。是JAVA中的商业应用lg技术。EJBl构中的角色 EJB lgl构是基于组件的分布式计结构,是分布式应用pȝ中的lg?br /> 一个完整的ZEJB的分布式计算l构由六个角色组成,q六个角色可以由不同的开发商提供Q每个角色所作的工作必须遵@Sun公司提供的EJB规范Q以保证彼此之间的兼Ҏ。这六个角色分别是EJBlg开发者(Enterprise Bean ProviderQ、应用组合者(Application AssemblerQ、部|者(DeployerQ、EJB服务器提供者(EJB Server ProviderQ、EJB 容器提供者(EJB Container ProviderQ、系l管理员QSystem AdministratorQ:
1.EJB中各角色的分?br /> Q?QEJBlg开发者(Enterprise Bean ProviderQ?br /> EJBlg开发者负责开发执行商业逻辑规则的EJBlgQ开发出的EJBlg打包成ejb-jar文g。EJBlg开发者负责定义EJB的remote和home接口Q编写执行商业逻辑的EJB classQ提供部|EJB的部|文Ӟdeployment descriptorQ。部|文件包含EJB的名字,EJB用到的资源配|,如JDBC{。EJBlg开发者是典型的商业应用开发领域专家?br /> EJBlg开发者不需要精通系l的编E,因此Q不需要知道一些系l的处理细节,如事务、同步、安全、分布式计算{?br /> Q?Q应用组合者(Application AssemblerQ?br /> 应用l合者负责利用各UEJBl合一个完整的应用pȝ。应用组合者有旉要提供一些相关的E序Q如在一个电子商务系l里Q应用组合者需要提供JSPQJava Server PageQ程序?br /> 应用l合者必L握所用的EJB的home和remote接口Q但不需要知道这些接口的实现?br /> Q?Q部|者(DeployerQ?br /> 部v者负责将ejb-jar文g部v到用Lpȝ环境中。系l环境包含某UEJB Server和EJB Container。部|者必M证所有由EJBlg开发者在部v文g中声明的资源可用Q例如,部v者必配|好EJB所需的数据库资源?br /> 部vq程分两步:部v者首先利用EJB Container提供的工L成一些类和接口,使EJB Container能够利用q些cd接口在运行状态管理EJB?部v者安装EJBlg和其他在上一步生成的cdEJB Container中。部|者是某个EJBq行环境的专家?br /> 某些情况下,部v者在部v时还需要了解EJB包含的业务方法,以便在部|完成后Q写一些简单的E序试?br /> Q?QEJB服务器提供者(EJB Server ProviderQ?br /> EJB 服务器提供者是pȝ领域的专Ӟ_N分布式交易理Q分布式对象理及其它系l的服务。EJB 服务器提供者一般由操作pȝ开发商、中间g开发商或数据库开发商提供?br /> 在目前的EJB规范中,假定EJB 服务器提供者和EJB 容器提供者来自同一个开发商Q所以,没有定义EJB 服务器提供者和EJB容器提供者之间的接口标准?br /> Q?QEJB 容器提供者(EJB Container ProviderQ?br /> EJB 容器提供者提供EJB部v工具为部|好的EJBlg提供q行环境 。EJB容器负责为EJB提供交易理Q安全管理等服务?br /> EJB 容器提供者必LpȝU的~程专家Q还要具备一些应用领域的l验。EJB 容器提供者的工作主要集中在开发一个可伸羃的,h交易理功能的集成在EJB 服务器中的容器。EJB 容器提供者ؓEJBlg开发者提供了一l标准的、易用的API讉KEJB 容器QEJBlg开发者不需要了解EJB服务器中的各U技术细节?br /> EJB容器提供者负责提供系l监工L来实时监EJB容器和运行在容器中的EJBlg状态?br /> Q?Q系l管理员QSystem AdministratorQ?br /> pȝ理员负责ؓEJB服务器和容器提供一个企业的计和|络环境?br /> pȝ理员负责利用EJB 服务器和容器提供的监管理工LEJBlg的运行情c?/p>
2.EJB的体pȝ构:
EJB分布式应用程序是Z对象lg模型的,低层的事务服务用了API技术。EJB技术简化了用JAVA语言~写的企业应用系l的开发,配置。EJB技术定义了一l可重用的组ӞEnterprise Beans。你可以利用q些lgQ象搭积木一L建立你的分布式应用程序。当你把代码写好之后Q这些组件就被组合到特定的文件中厅R每个文件有一个或多个Enterprise BeansQ在加上一些配|参数。最后,q些Enterprise Beans被配|到一个装了EJB容器的^C。客戯够通过q些Beans的home接口Q定位到某个beansQƈ产生q个beans的一个实例。这P客户p够调用Beans的应用方法和q程接口?br /> EJB服务器作为容器和低层q_的桥梁管理着EJB容器和函数。它向EJB容器提供了访问系l服务的能力。例如:数据库的理和事务的理Q或者对于其它的Enterprise的应用服务器。所有的EJB 实例都运行在EJB容器中?br /> 容器提供了系l的服务,控制了EJB的生命周期。EJB中的有一些易于用的理工具如:
SecurityQ配|描q器QThe Deployment descriptorQ定义了客户能够讉K的不同的应用函数。容器通过允许授权的客戯问这些函数来辑ֈq个效果?br /> Remote ConnectivityQ容器ؓq程链接理着低层的通信issuesQ而且对Enterprise Beas的开发者和客户都隐藏了通信l节。EJB的开发者在~写应用Ҏ的时候,p是在条用本地的^CL。客户也不清楚他们调用的Ҏ可能是在q程被处理的?br /> Life Cycle managmentQ客L单的创徏一个Enterprise beans的实例,q常取消一个实例。而容器管理着Enterprise Beans的实例,使Enterprise Beans实现最大的效能和内存利用率。容器能够这hȀzd使Enterprise Beans失效Q保持众多客户共享的实例池。等{?br /> Trasction managementQ配|描q器定义了Enterprise beans 的事务处理的需求。容器管理着那些理分布式事务处理的复杂的issues。这些事务可能要在不同的q_之间更新数据库。容器ɘq些事务之间互相独立Q互不干扰。保证所有的更新数据库都是成功发生的Q否者,回滚到事务处理之前的状态?br /> EJBlg是基于分布式事务处理的企业应用E序的组件。所有的EJB都有如下的特点:
EJB包含了处理企业数据的应用逻辑Q定义了EJB的客L面。这L界面不受容器和服务器的媄响。于是,当一个EJB被集合到一个应用程序中LQ不用更改代码和重新~译?br /> EJB能够被定制。各U系l的服务,例如安全和事务处理的Ҏ,都不是属于EJBcȝ。而是由配|和l装应用E序的工h实现?br /> 有两U类型的EJBQ?Session beans ?entity beans。Session beans是一U作为单用户执行的对象。作为对q程的Q务请求的相应Q容器生一个Session beans 的实例。一个Session beans有一个用戗从某种E度上来_一个Session bean 对于服务器来说就代表了它的那个用戗Session beans 也能用于事务Q它能够更新׃n的数据,但它不直接描l这些共享的数据。Session beans 的生命周期是相对较短的。典型的是,只有当用户保持会话的时候,Session beans 才是zȝ的。一旦用户退ZQSession beans ׃再与用户相联pM。Session beans被看成是瞬时的,因ؓ如果容器崩溃了,那么用户必须重新建立一个新的Session对象来l会话?br /> Session bean典型的声明了与用L互操作或者会话。也是_Session bean在客户会话期_通过Ҏ的调用,掌握用户的信息。一个具有状态的Session beanUCؓ有状态的Session bean。当用户l止与Session beans互操作的时候。会话终止了Q而且Qbean 也不再拥有状态倹{Session bean也可能是一个无状态的 session bean。无状态的Session beansq不掌握它的客户的信息或者状态。用戯够调用beans的方法来完成一些操作。但是,beans只是在方法调用的时候才知道用户的参数变量。当Ҏ调用完成以后Qbeansq不l箋保持q些参数变量。这P所有的无状态的session beans的实例都是相同的Q除非它正在Ҏ调用期间。这P无状态的Session beansp够支持多个用戗容器能够声明一个无状态的Session beans。能够将MSession beans指定lQ何用戗?br /> Entity BeansҎ据库中的数据提供了一U对象的视图。例如:一个Entity bean能够模拟数据库表中一行相关的数据。多个client能够׃n讉K同一个Entity bean。多个client也能够同时的讉K同一个Entity bean。Entity beans通过事务的上下文来访问或更新下层的数据。这P数据的完整性就能够被保证。Entity Beans能存zȝҎ长的旉Qƈ且状态是持箋的。只要数据库中的数据存在QEntity beans׃直存zR而不是按照应用程序或者服务进E来说的。即使EJB容器崩溃了,Entity beans也是存活的。Entity Beans生命周期能够被容器或?Beans自己理。如果由容器控制着保证 Entity beans持箋的issus。如果由Beans自己理Q就必须写Entity beans的代码,包括讉K数据库的调用?br /> Entity Beans是由主键Qprimary key 一U唯一的对象标识符Q标识的。通常Q主键与标识数据库中的一块数据,例如一个表中的一行,的主键是相同的。主键是client能够定位特定的数据块?
利用EJBq行开发有哪些步骤Q?
开发EJB的主要步骤一般来_整个的开发步骤(开发,配置Q组装)包括如下几个斚w?br /> ·开发:首先要定义三个类QBeancLw,Bean的本地和q程接口cR?br /> ·配置Q配|包括生配|描q器Q这是一个XML文g、声明了Enterprise Bean的属性、绑定了bean的class文gQ包括stub文g和skeleton文gQ。最后将q些配置都放C个jar文g中。还需要在配置器中定义环境属性?br /> ·l装应用E序Q包括将Enterprise beans安装到Server服务器中Q测试各层的q接情况。程序组装器若q个Enterprise Beans与其它的lgl合hQ组合成一个完整的应用E序Q或者将若干个Enterprise beansl合成一个复杂的Enterprise Bean?br /> ·理Enterprise Bean
必须定义和编写一些EJB中的基本cR如Enterprise beanc:q是Enterprise bean内部应用逻辑的实现。编写Enterprise bean的远E接口类。编写Enterprise bean的本地接口类。说明主键类Q主键类只是对于Entity bean才需要的。在Enterprise bean的配|描q器中指定主键的名字。Enterprise beans提供者定义了q程接口和本地接口,实现了EJBcLw。Remote接口中提供了客户调用EJB实现的应用逻辑函数的接口。而home接口提供了生和定位remote接口实例的方法?
在Enterprise bean本ncȝ实现Q本地home接口Q远Eremote接口之间q没有正式的联系Q例如承关p)。但是,在三个类里声明的Ҏ却必遵守EJB里面定义的规范。例如: 你在Enterprise bean里面声明了一个应用程序的Ҏ或者说应用逻辑。也在beans的remote接口中声明了q个ҎQ那么,q两个地方必要同样的名字。Bean的实现里面必至有一个Create()ҎQejbCreate()。但是可以有多个带有不同参数的create()Ҏ。在home接口中,也必L相同的方法定义(参数的个数相同)。EjbCreate()Ҏq回的一个容器管理的持久对象。它们都q回一个容器管理持久性的主键倹{但是,在home的相应的Create()Ҏ中返回值的cd是remote接口?br /> 注意Q实体bean的实现的ejbCreateҎ有点不同。实体bean可以不定义ejbCreateҎ。如果实体只是通过应用E序或通过数据库管理程序的途径被加到数据库中,实体beanq略了ejbCreateҎ。EjbCreateq回的值是主键cd。如果ejbCreateҎ是容器管理持久性的实体bean的方法,它的q回值就是NULLcd。如果实体bean实现了Bean理的持久性,ejbCreateҎp回值类型就是主键类型。容器的d是把各接口和Enterprise bean的实现类l合h。保证在~译时和q行Ӟ各接口和实现cL相对应的?
EJB的实现类Q各接口要从不同的基cMl承下来。一个会话bean必须实现基类Javax.ejb.SessionBean。而实体bean必须实现基类Javax.ejb.EntiyBean。这些EJB的基c都是从Javax.ejb.EnterpriseBeanl承而来。而Javax.ejb.EnterpriseBean又是从Java.io.Serializablel承而来。每一个Enterprise Bean都必L一个remote接口。Remote接口定义了应用程序规定客户可以调用的逻辑操作。这些是一些可以由客户调用的公qҎQ通常由Enterprise beanscL实现。注意,Enterprise bean的客户ƈ不直接访问Bean。而是通过remote接口来访问。Enterprise beancȝremote接口扩展了Javax.ejb.EJBObjectcȝ公共Java接口。而Javax.ejb.EJBObject是所有remote接口的基cR其代码如下Q?
package Javax.ejbQ?
public interface EJBObject extends Java.rmi.Remote{
public EJBHome getEJBHome() throws Java.rmi.RemoteExceptionQ?
public Object getPrimaryKey() throws Java.rmi.RemoteExceptionQ?
public void Remove() throws Java.rmi.RemtoeExceptionQ?Java.rmi.RemoveException
public Handle getHandle() throws Java.rmi.RemoteExceptionQ?br />boolean isIdentical (EJBObject p0) throws Java.rmi.RemoteExceptionQ?
}
getEJBHome()Ҏ允许你取得一个相关的Home接口。对?实体BeanQ用getPrimaryKey()Ҏ获得实体Bean的主键倹{Remove()可以删除一个Enterprise bean。具体的语义在各U不同类型的enterprise beans的生命周期中Q由上下文中解释的。方法getHandle()q回了一个Enterprise bean实例的持久的句柄。IsIndentical()Ҏ允许你去比较Enterprise beans是否相同?
所有的remote接口中的Ҏ必须声明为公共(publicQ的Qƈ必须抛出Java.rmi.RemotException异常。另外,所有的remote接口中的Ҏ定义的参数和都必L在RMI-IIOP中有效的。对每一个在remote接口中定义的ҎQ在Enterprise bean c里面都要有相应的方法。相应的Ҏ必须要有同样的名字,同样cd和数量的参数Q同Lq回|而且q要抛出同样的例外?如下代码昄了一个ATM例子的会话bean的remote接口Atm。里面声明了一个应用方法transfer()。黑体部分表CEJB规范中必要有的内容。Remote接口必须扩展Javax.ejb.EJBObjectcR从客户端调用的Enterprise bean的每一个方法都必须在remote接口中声明。Transfer()Ҏ抛出了两个意外。其中InSufficientFundsException例外是应用程序定义的意外?
Public interface Atm extends Javax.ejb.EJBObject{
Public void transfer(String SourceQ?String TargetQ?float amount)
Throws Java.rmi.RemoteExceptionQ?InSufficientFundsExceptionQ?
}
Home接口必须定义一个或多个的Create()Ҏ。每一个这LCreate()Ҏ都必d名ؓCreate。ƈ且,它的参数Q不是cdq是数量都必Mbeanc里面的ejbCreate()Ҏ对应。注意,home接口中的Create()Ҏ和beancMejbCreate()Ҏ的返回值类型是不同的。实体bean的home接口q包含find()Ҏ?每一个Home接口都扩展了Javax.ejb.EJBHome接口。如下代码显CZJavax.ejb.EJBHome接口的定义:
package Javax.ejbQ?
public interface EJBHome extends Java.rmi.Remote() {
void remove(Handle handle) throws Java.rmi.RemoteExceptionQRemoveExceptionQ?
void remove(Object primarykey) throws Java.rmi.RemoteExceptionQRemoveExceptionQ?
EJBMetaData getEJBMetaData() throws RemoteExceptionQ?
Homehandle getHomeHandle() throws RemoteExceptionQ?
}
q里提供了两个remove()Ҏ来删除Enterprise bean的实例。第一个removeҎ是通过句柄来删除一个Enterprise bean的实例。第二个removeҎ通过主键来删除一个Enterprise bean的实例?在众多的Enterprise bean实例中,句柄唯一的标识一个实例。一个句柄与它引用的Enterprise bean有相同的生命期。考虑一个实体对象,客户可以通过一个句柄来重新获得相应的Enterprise bean的实例。一个句柄能够对应一个Enterprise bean对象的多个实例。例如,即当Enterprise bean对象所在的L崩溃了,或者Enterprise bean对象在不同的机器之间UdQ句柄仍是有效的。这里的句柄是Serialized句柄Q与CORBA中的字符串化的CORBA对象的引用是怼的概c在EJBHome接口中的W二个remove操作通过其主键来军_要删除的Enterprise bean。主键可以是扩展了Java ObjectcȝMcdQ但是,必须要实现Java的Serializable接口。主键是标识实体bean的主要的Ҏ。通常Q主键是数据库中的一个关键字Q唯一的定义了由实体bean代表的数据?
ҎgetEJBMetaData()q回了Enterprise bean对象的metadata接口。这个接口允许客戯得Enterprise bean的metadata信息。当开发工h~译链接应用E序的时候,或者配|工h配置的时候,可能会用到metadata信息。 Javax.ejb.EJBMetadata接口提供了获得Javax.ejb.EJBHome接口Qhomec,remote接口Q还有获得主键的Ҏ。也提供了一个isSesson()的方法来定在放q个home接口的对象是会话beanq是实体bean?br /> IsStatelessSession()Ҏ指示q个会话bean是有状态还是无状态的。如下代码显CZJavax.ejb.EJBMetadata接口的定义部分的代码?
Public Javax.ejbQ?Public interface EJBMetaData{
EJBHome getEJBHome()Q?br />Class getHomeInterfaceClass()Q?
Class getRemoteInterfaceClasss()Q?br />Class getPrimaryKeyClass()Q?
Boolean isSession()Q?br />Boolean isStatelesssSession()Q?
}
Ҏ一个Create()ҎQEJB规范定义了如下的命名U定。它的返回值是会话bean的remote接口的类型。方法的名字只能是Create()。对会话beancM的每一个ejbCreate()Ҏ都必L一个Create()与之对应?对于每一个Create()Ҏ的参数的cd和数量都必须与会话beancM的ejbCreate()Ҏ相对应。方法必L出Java.rmi.RemoteException例外?Ҏ必须抛出Javax.rmi.CreateExeption例外?Create()Ҏ的参数是用来初始化新的会话bean对象的。如下代码显CZ一个会话bean对象的不同的Create()ҎQ其中必ȝ部分用粗体显C:
public interface AtmHome extends Javax.ejb.EJBHome{
Atm create() throws Java.rmi.RemoteExceptionQJavax.ejb.CreateExceptionQ?
Atm create(Profile preferredProfile)
Throws Java.rmi.RemoteExeptionQJavax.ehrows Java.rmi.RemoteExceptionQRemoveExceptionQ?
EJBMetaData getEJBMetaData() throws RemoteExceptionQ?
Homehandle getHomeHandle() throws RemoteExceptionQ?
}
q里提供了两个remove()Ҏ来删除Enterprise bean的实例。第一个removeҎ是通过句柄来删除一个Enterprise bean的实例。第二个removeҎ通过主键来删除一个Enterprise bean的实例。在众多的Enterprise bean实例中,句柄唯一的标识一个实例。一个句柄与它引用的Enterprise bean有相同的生命期。考虑一个实体对象,客户可以通过一个句柄来重新获得相应的Enterprise bean的实例。一个句柄能够对应一个Enterprise bean对象的多个实例。例如,即当Enterprise bean对象所在的L崩溃了,或者Enterprise bean对象在不同的机器之间UdQ句柄仍是有效的。这里的句柄是Serialized句柄Q与CORBA中的字符串化的CORBA对象的引用是怼的概c?
在EJBHome接口中的W二个remove操作通过其主键来军_要删除的Enterprise bean。主键可以是扩展了Java ObjectcȝMcdQ但是,必须要实现Java的Serializable接口。主键是标识实体bean的主要的Ҏ。通常Q主键是数据库中的一个关键字Q唯一的定义了由实体bean代表的数据。方法getEJBMetaData()q回了Enterprise bean对象的metadata接口。这个接口允许客戯得Enterprise bean的metadata信息。当开发工h~译链接应用E序的时候,或者配|工h配置的时候,可能会用到metadata信息。Javax.ejb.EJBMetadata接口提供了获得Javax.ejb.EJBHome接口Qhomec,remote接口Q还有获得主键的Ҏ。也提供了一个isSesson()的方法来定在放q个home接口的对象是会话beanq是实体bean。IsStatelessSession()Ҏ指示q个会话bean是有状态还是无状态的。 如下代码昄了Javax.ejb.EJBMetadata接口的定义部分的代码?
Public Javax.ejbQ?
Public interface EJBMetaData{
EJBHome getEJBHome()Q?
Class getHomeInterfaceClass()Q?br />Class getRemoteInterfaceClasss()Q?
Class getPrimaryKeyClass()Q?
Boolean isSession()Q?
Boolean isStatelesssSession()Q?
}
EJB的编E环境有哪些Q?
1. 使用Jbuilder
Jbuilder与EJB Container能够q行无缝q接。Jbuilder和Inprise的应用服务器包括了所有的开发和配置Enterprise Beans的工具以及所需要的库:q行和管理Enterprise Bean的容器、命名服务?事务服务、Java数据库、开发Enterprise Beans所需要的API、一个增强的Java-to-iiop~译器,支持值类型和RMI信号{等?
Jbuilderq提供了一个快速开发应用程序Enterprise Beans的工具和向导。通过单而且直观的步骤,向导帮助你徏立一个Enterprise Bean。自p定某些缺省|产生了bean的模板,在上面,我们可以增加我们自己的应用逻辑。Jbuilder也提供了一个EJB的接口生成向对{向导在Enterprise Bean的公共方法基上生成了Remote接口和Home接口。Jbuilderq提供一个配|器的向导帮助我们逐步的徏立XML描述器文件。ƈ生成的Stubs集中C个jar文g中?
2.使用Jbuilder之外的集成环境:
如果你用其它的除了别的集成环境QIDEQ。要定使用了集成环境IDE所带的容器工具。也要验证IDE是否支持EJB规范的相应的版本Q还要确定它是否正确的支持EJB的API?
要确定JD到所支持的EJB容器的版本。可以通过查Inprise的安装说明来定EJB容器所支持的支持JDK的版本?
在配|Enterprise Bean的时候,你必M用Inprise的应用服务器所提供的工兗这些工兯够编辑和修改W三方的代理商提供的Inprise配置描述器。还能够验证配置描述器,能够验证bean的源代码?
附录Q一个具体而微的EJB应用实例Q?
1.安装Apusic Application Server
NoteQ以下以LinuxZQ来说明Apusic Application Server的安装过E。其他^台的安装Q可参考Apusic Application Server安装手册?
下蝲JDK1.2QApusic Application Server必须q行在JDK1.2以上环境中。可从以下站点下载最新JDK?
httpQ?/Java.sun.com
下蝲Apusic Application Server
Apusic Application Server 试用版可从以下网址得到Q?
httpQ?/www.apusic.com/download/enter.jsp
在下载完成后Q你可以得到一个包Ҏ件apusic.zipQ选定安装目录Q假讑֮装到/usr下,则用以下命oQ?
cd /usr
jar xvf apusic.zip
/usr下会出现一个目录apusicQApusic Application Server的所有程序都被解压到/usr/apusic下?
以下\径加入到CLASSPATH?
/usr/apusic/lib/apusic.jar
$JAVA_HOME/lib/tools.jar
用以下命令运行Apusic Application Server
Java -Xms64m com.apusic.server.Main -root /usr/apusic
2.定义EJBq程接口QRemote Interface)
M一个EJB都是通过Remote Interface被调用,EJB开发者首先要在Remote Interface中定义这个EJB可以被外界调用的所有方法。执行Remote Interface的类由EJB生成工具生成。以下是HelloBean的Remote IntefaceE序Q?
package ejb.helloQ?
import Java.rmi.RemoteExceptionQ?br />import Java.rmi.RemoteQ?br />import Javax.ejb.*Q?
public interface Hello extends EJBObjectQ?Remote {
// this method just get "Hello World" from HelloBean.
public String getHello() throws RemoteExceptionQ?br />}
3.定义Home Interface
EJB容器通过EJB的Home Interface来创建EJB实例Q和Remote Interface一P执行Home Interface的类由EJB生成工具生成。以下是HelloBean 的Home InterfaceE序Q?
package ejb.helloQ?
import Javax.ejb.*Q?br />import Java.rmi.RemoteQ?br />import Java.rmi.RemoteExceptionQ?br />import Java.util.*Q?
/**
* This interface is extremely simple it declares only
* one create method.
*/
public interface HelloHome extends EJBHome {
public Hello create() throws CreateExceptionQ?
RemoteExceptionQ?
}
4.写EJBc?br /> 在EJBcMQ编E者必ȝ出在Remote Interface中定义的q程Ҏ的具体实现。EJBcMq包括一?EJB规范中定义的必须实现的方法,q些Ҏ都有比较l一的实现模版,~程者只需p_֊在具体业务方法的实现上。以下是HelloBean的代码:
package ejb.helloQ?
import Javax.ejb.*Q?br />import Java.util.*Q?br />import Java.rmi.*Q?
public class HelloBean implements SessionBean {
static final boolean verbose = trueQ?
private transient SessionContext ctxQ?// Implement the methods in the SessionBean
// interface
public void ejbActivate() {
if (verbose)
System.out.println("ejbActivate called")Q?br />}
public void ejbRemove() {
if (verbose)
System.out.println("ejbRemove called")Q?br />}
public void ejbPassivate() {
if (verbose)
System.out.println("ejbPassivate called")Q?br />}
/**
* Sets the session context.
*
* @param SessionContext
*/
public void setSessionContext(SessionContext ctx) {
if (verbose)
System.out.println("setSessionContext called")Q?br />this.ctx = ctxQ?br />}
/**
* This method corresponds to the create method in
* the home interface HelloHome.Java.
* The parameter sets of the two methods are
* identical. When the client calls
* HelloHome.create()Q?the container allocates an
* instance of the EJBean and calls ejbCreate().
*/
public void ejbCreate () {
if (verbose)
System.out.println("ejbCreate called")Q?br />}
/**
* **** HERE IS THE BUSINESS LOGIC *****
* the getHello just return a "Hello World" string.
*/
public String getHello()
throws RemoteException
{
return("Hello World")Q?br />}
}
5.创徏ejb-jar.xml文g
ejb-jar.xml文g是EJB的部|描q文Ӟ包含EJB的各U配|信息,如是有状态BeanQStateful BeanQ?q是无状态BeanQStateless BeanQ,交易cd{。ejb-jar.xml文g的详l信息请参阅EJB规范。以下是HelloBean的配|文Ӟ
Hello
ejb.hello.HelloHome
ejb.hello.Hello
ejb.hello.HelloBean
Stateless
Container
Hello
*
Required
6.~译和部|?br /> ~译Java源文件ƈ编译后class和ejb-jar.xml打包到Hello.jar
mkdir build
mkdir build/META-INF
cp ejb-jar.xml build/META-INF
Javac -d build *.Java
cd build
jar cvf Hello.jar META-INF ejb
cd ..
用EJB工具生成可部|到Apusic Application Server中运行的jar文gQ?
Java com.apusic.ejb.utils.EJBGen -d /usr/apusic/classes/Hello.jar build/Hello.jar
增加/usr/apusic/classes/Hello.jar到CLASSPATH?
Hello.jar加入到Apusic Application Server配置文g中。在/usr/apusic/config/server.xml 加入以下几行Q?
classes/Hello.jar
Hello
HelloHome
启动服务?
Java -Xms64m com.apusic.server.Main -root /usr/apusic
7.写客L调用E序
现在读者可以从Java ClientQJSPQServlet或别的EJB调用HelloBean?
调用EJB有以下几个步骤:
·通过JNDIQJava Naming Directory InterfaceQ得到EJB Home Interface
·通过EJB Home Interface 创徏EJB对象Qƈ得到其Remote Interface
·通过Remote Interface调用EJBҎ
以下是一个从Java Client中调用HelloBean的例子:
package ejb.helloQ?
import Javax.naming.ContextQ?br />import Javax.naming.InitialContextQ?br />import Java.util.HashtableQ?br />import Javax.ejb.*Q?br />import Java.rmi.RemoteExceptionQ?
/**
* @author Copyright QcQ?2000 by ApusicQ?Inc. All Rights Reserved.
*/
public class HelloClient{
public static void main(String args[]){
String url = "rmiQ?/localhostQ?888"Q?br />Context initCtx = nullQ?br />HelloHome hellohome = nullQ?br />try{
Hashtable env = new Hashtable()Q?br />env.put(Context.INITIAL_CONTEXT_FACTORYQ?br />"com.apusic.jndi.InitialContextFactory")Q?
env.put(Context.PROVIDER_URLQ?url)Q?
initCtx = new InitialContext(env)Q?br />}catch(Exception e){
System.out.println("Cannot get initial contextQ?" + e.getMessage())Q?br />System.exit(1)Q?br />}
try{
hellohome = (HelloHome)initCtx.lookup("HelloHome")Q?
Hello hello = hellohome.create()Q?br />String s = hello.getHello()Q?br />System.out.println(s)Q?
}catch(Exception e){
System.out.println(e.getMessage())Q?br />System.exit(1)Q?br />}
}
}
q行HelloClientQ可得到以下输出QHello World