16.3.2 EJB 编程

 
EJB依祺它的容器提供所有的外部信息。如果EJB需要访问某个JDBC连接或者另 个bean,那么,它使用容器服务。访问其调用者的身份.获得对其自身的引用以及访问特 性都是通过容器服务完成的。这是一个使用“仲裁者”战术的示例。Bean通过以下某个机 制与它的,容器交互:回调方法、EJBContext接口、Java命名和目录接口。
 
开发人员要创建EJB服务器端组件,必须提供定义了 bean的业务方法的两个接口以 及实际的bean实现类。图丨6.5给出了这两个接口: remote和home。客户端使用它们访问 EJB咨器中的bean。它们展露了这个bean的功能,并且提供了创建、更新、与之交互或 将其删除所需的全部方法。
 
这两个接口有不同的用途。home包含了 EJB的生命期方法,这些方法为客户端提供 了创建、销毁和査找bean实例的服务。而remote包含了由bean提供的业务方法。这些方 法是特定于应用的。如果要在bean的remote接口中使用这些方法,客户端必须使用bean 的home接口来获得对remote接口的引用。
图16.6给出了一个简单的home接口。home接口必须继承自EJBHome,在本例中. 它包含了 一个创建Broker类的EJB的方法。图16.7给出/ Broker类EJB的remote接口,
 
 
Remote接口必须扩展EJBObject接口,后者包含了许多容器用于管理EJB的创建和生 命期的方法。程序员可能希望为EJB提供特定于bean的行为,也有吋能只是接受默认的、 继承来的行为。然后,客户端使用public接口创建、操作bean,并将其从EJB服务器中移 除。实现类(通常也称为bean类〉在运行时被实例化,它成了 .个可i方问的分布式对象。 图16.8中给出了 -些简化后的客户端示例代码。
 
后面我们将会看到,EJB客户端可能是单独的应用、servlet, applet甚至是其他的EJB„ 所有的客户端使用服务器bean的home接口获得对服务器bean的某个实例的引用。该引 用与服务器bean的remote接口的类类型相关联,因此客户端与服务器bean的交互完全是 使用在其remote接口中定义的方法实现的。
 
在下-个示例中,Broker类bean充当一•个处理所有客户端请求的无状态会话bean。在内部,它使用大量实体bean的服务执行业务逻辑。图丨6.9给出了 Broker方法的一个示 例-updateAccount。
 
updateAccount方法使用了 -个称为Account的实体bean。 Account封装了应用数据的 所存详细的操纵倍息,本例中封装了如何更新一个账户记录的信息。updateAccount中的代 码使用了 -个称为findByPrimaiyKey的实体bean的finder方法,它由其home接口中的 Account bean提供。该方法先获取账户的主键,然后访问下层的数据厍。如果用获取的主 键在数据库中找到了 -个账户记录,EJB容器就会创逑一个Account实体beaiu然实 体bean //法(本例中为update)可以用来访问账户记录中的数据。阌16.10中给出了 Account 的 home 和 remote 接口。
 
实体bean的bean类实现了 remote方法。图16.11给出了 update方法的代码-该方法 十分简舉,实际上只有行可执行的java代码。这种简单性足由于采用了容器管埋的持久 性。EJB容器“知道”(我们不久就会看到)在Account bean的数据成员和应用正使用的 数据库中的账户表的字段之间有-个对应。
容器工具可以使用此信息生成实现finder方法所滿的SQL杏洵,以及在事务幵始时从 实体bean自动读取数据(在事务结束时自动将数据写入实体bean)所需的查询。在本例 中,在Broker会话bean的updateAccount方法结束时,Account实体bean中的数掘项被 写回数据库,从而使得对sub_Credit字段的更改持久。完成上面的工作不需要程序员进行 明确的控制,从而促成了基r EJB的系统的可构建性。
 
16.3.3部署描述符
 
EJB在业务逻辑和基础结构代码间分离关注点的方式,是它吸引人的•个方面(这是 “语义•致性”战术的-个示例)。该分离指的是如下事实,即EJB主要关注的是纯粹的 业务逻辑,而EJB容器处理的是环境和基础结构问题(如事务、bean生命期管理和安全性)。 这使得bean组件更加简单——这些组件中没有用来处理这些额外复杂性的代码。
 
bean通过部署描述符告知容器在所提供的服务中,哪个是它所需要的。这是一个与 EJB相关的XML文档。在容器中部署了 bean后,容器会读取部署描述符,以发现应该如 何处现事务、持久性(为实体bean)和访问控制。因此,描述符提供了一种如何处理这些问题的描述性机制——这是“推迟绑定时间”战术的•个示例。
 
该机制的奇妙之处进,可以为同一个组件部署适合不同应用环境的不同描述符。如果 关注的是安全性问题.组件可以指定其访问控制的需求。杏则,就不指定访问控制的需求。 在这两种情况中,EJB中的代码是完全一样的。
 
部署描述符有•个预定义的格式,所有遵从EJB的bean都必须采用该格式.并且所 有遵从EJB的服务器都必须知道如何读取该格式。该格式是在-个XML Document Type Definition (DTD)中指定的。部署描述符描述了 bean的类型(会话或实体)、用于remote 和home的类和bean类。它还指定了 bean中每种方法的事务属性。它们描述了哪个安全 性角色可以访问所有的方法(访问控制)和实体bean中的持久性是否由容器自动处理或显式地由bean代码执行。
 
图16.12给出了前面说明过的Broker bean的部署描述符。除了前面所描述的属性外, 图中的部署描述符还确定了这是一个无状态会话bean,并且需要一个容器管理的事务来执 行该bean的所有方法(为了便于阅读.这些属性在图中以粗体的形式标识)。例如.如 果我们只是将XML中的<session-type>字段改为读取statefull,则容器将以有很大不同的方 式来管理该bean。图丨6.13给出了 Account实体bean的部署描述符。除了已经看到的部署 属性外,它还告知了容器以下信息:
 
•    它必须为这种类型的bean管理持久性„
 
•    为数据库查找JDBC数据源的位置„
 
•    必须在数据库和实体bean之间映射哪个主键和数据项。
 
在表16.2中,我们给出了 Sun对J2EE的质最属性衢求。在表16.5中,我们描述了如 何通过部署描述符满足这些需求。
表16.5部署描述符如何支持Sun的J2EE质置厲性需求
16.4系统部署决策
 
迄今为止,我们所描述的是由Sun创建的J2EE/EJB。然而.在部辨J2EE/EJB系统时, 设计师还滞要考虑许多关于实现的问题。EJB组件模型足构边服务器端他用的强大方法。 尽管代码不同部分之间的交互刚开始时让人有些沮丧,伹在对该模型有了一些了解并具备 了工作经验之后,EJB应用的构建相对来说就简单了。然而,虽然代码的构建并不困难. 但仍然存在许多复杂性.下面列出了其中的一部分:
 
•    EJB模型使得可以用多种不同的构架模式组合应用中的组件„哪咚模式最佳?在 给定的应用中.最佳的含义是什么?
 
•    bean与容器的交互方式是复杂的.并且会对应用的性能产生巨大的影响。同样. 所有的EJB服务器容器并不是同等重要的——产品选择和特定于产品的配置是 应用开发生命期的重要方面。
 
本节我们讨论了些涉及构架和构建高度可扩充的EJB应用的关键的设计问题。
 
16.4.1状态管理:新环境下旧的设计问题
 
目前有两种服务模型可用于开发EJB服务器层——无状态和状态榄型,它们是由无状 态和状态会话bean实现的。
 
我们将以•个在线书店为例。在采用状态模型的版本中,可以用使用EJB來记录客户 的详细惝况,并管理客户放入在线购物车中的物品。因此.EJB保存了与客户访问该站点 相关的状态。通过在bean中维护该对话状态,免去了客户端跟踪该状态的职责。EJB会监 视潜在的购买,并且在凋用某个确认方法时对其进行批处理。
 
为了更好地利用有限的系统内存,当客户端不使用状态会话bean时,它将被钝化。 这意味葙bean的对话状态被写入到辅助存储器中(通常是磁盘).并且其实例从内存中移 除。客户端对bean的引用并不受钝化影响,它仍然有效并且是可用的。当客户端在某个 被钝化的bean上调用某个方法时,容器通过实例化•个新的实例并将写入到辅助存储器中的信息填入其状态中,从而激活bean。
 
钝化策略对于可扩充性蕴含着巨大的意义。如果需要大量的状态会话bean实例为单 个的客户端服务,则从应用性能方面说,钝化和激活的开销可能过高。
 
作为替代方案.无状态会话bean不会代表客户维护对话状态。对子毎次服务清求, 客户端都必须将会话信息告知服务器,如客户的详细信息和购物车中的内'容’这是因为容 器可以为每个请求分配一个不同的无状态会话bean实例。这仅发生在纯粹的无状态服务 模型中。图16.14给出了状态和无状态会话bean的使用。
 
概括起来,无状态会话bean包括如下优点:
 
•    没有纯化和激活会话bean (涉及大量磁盘读写)的性能幵销、
 
•    动态请求路由意味着可以将请求路由到负载最小的服务器
 
•    如某个会话实例结束了,则可以轻松地将请求重新路由给另一个实例。
 
美中不足的是.对于每个请求,无状态方法都需要在客户端和EJB之间传递更多的信 息。若非数据量大得惊人,无状态会话bean能更好地支持极萵的系统扩允性。
 
是否使用实体bean
 
-个通常使用的EJB设计模式是:提供一个包装器会话bean.它向客户端暴露服务. 同时访问封装在实体bean中的业务数据,以满足客户端的请求。这展示了…个很淸晰的 面向对象编程模彻。业务数据通常用数据库中的关系格式表示,但现在以面向对象的格式 (实体bean)封装了起来。为实体bean定义的各种get和set方法使得会话bean能便捷地 访问这些数据。另外•如果容器管理的持久性用于实体bean.那么数据库开发人员+需要 直接开发数据库访问代码。
 
使用实体bean的风险是巨大的性能损失。测试结果表明.对于-•个典型的具有85% 只读和15%更新业务的电子商务系统,使用实体bean的应用构架的系统吞吐量l:大约只有 使用会话bean的应用构架的一半。导致性能降低的原因有以下几点:
 
•    与会话bean笪接访问数据库中的业务对象相比,实体bean引入了 •个额外的间 接的层。容器可能不会自动将对实体bean的调用优化为本地调用,这取决于采 用的是哪种容器实现。在这个例子中,额外的RMI凋用的幵销很大
 
•    在该额外层中,实体bean的生命期管理可能引起很大的开销。激活的开销至少 相当于一个数据库/磁盘读取操作,钝化相当于-个数据库/磁盘写入操作。
 
•    额外的bean参与了事务。
 
当然,应该由设计师来决定与很可能会出现的系统吞吐量的降低相比,实体bean所 具备的优点是否史重要-
 
16.4.2分布和扩充问题
 
随着支持Web的企业系统的普及,许多企业发现它们的后端系统无力处理巨大的 Interne信息流量。在服务器层,有两种提高该处理能力的方法:
 
•    “纵向”扩允指的是增加计算和系统资源。比如,为单机增加内存。这种形式的 扩充依赖子应用服务器的内部构架中没有固有的瓶颈。如果这•条件成立,只要 提供更多的系统资源和处理能力,应用服务器软件就能充分地利用额外的资源, 从而增加系统的吞吐量。
 
•    “横向”扩充是指将服务器应用分布到多个机器上.而非用-个史强大的模型代 替现在的机器。通过为应用提供额外可用的机器,可以增加系统的总体资源和处 理能力。
 
通常认为横向扩充比纵向扩充更难实现,因为它需要更复杂的配置和系统管理。应用 服务器还必须提供平衡负载的机制,以确保客户端充分利用不同机器上的额外资源。
 
尽管如此,运行在多台机器上的系统确实能比运行在单个大型机上的系统具有更多的 优点:
 
•    增加冗余。如果某台机器出现故障,还有其他机器可以接替其工作。机器可能会 断电、网络故障、操作系统瘫痪、应用服务器故陣或者应用代码本身的缺陷而 出现故陣。
 
•    经济高效。一个由多台小型机器组成的网络可能比单个大型机器有更卨的性价比。
 
许多应用商品提供集群服务,以支持应用的横向扩充。再次强调,集群产品差异甚大, 构架师需要仔细分析这些差别。
 
分布式車务
 
许多EJB服务器都能够对事务进行协调。这些事务涉及驻留在一个分布式系统的各个 进程中的多个对象。使用两阶段提交协议的分布式事务处理是构建企业范围内的系统的基 本要素。
 
构架师在设计EJB系统时需要认真考虑是否需耍采用分布式事务。这进因为管理分布 式事务需要开销,而且开销会随着事务参与者的增加而变大。如果不需要在多个资源管理 器(或数据痄)中协调该事务,也就不需要采用两阶段提交协议。
 
而且,事务协调和提交过程可能需要几个通过网络传递的远程调用。这可能发生在EJB 服务器(或容器〉与外部事务管理过程之间。如果由EJB服务器提供的分布式事务实现导 致了额外的协调办务的远程调用需求,则分布式亊务的使用可能会极大地降低系统的性能,并抑制整体系统的可扩充性。
 
根据我们对各种对象技术管理和J2EE实现的了解,各种分布式审务管理间存在很大 的性能羞异。因此,对于-个给定的事务服务.应用设计师要全面理解可用的配置和部署 选择.这一点非常重要*
 
16.4.3资源共享
 
在分布式系统中,必须谨慎地对应用资源(如数据库连接和套接字)进行管理。并不 是所有的客户端都潘要•直单独访问某个资源,资源池就是利用了这事实。对于EJB.
 
并不是每.个bean都滿要自己专用的数据库连接。因此,更高效的做法是,对系统进行配置,从而使得对于不同的客户端事务,可以共享和重用数据库连接。
 
使用数据庳连接池时,要求得到的连接的数目远小于已部署系统中EJB组件的数目。 因为创建和赞理数据痄连接的开销很大,所以该构架提高了整体应用的可扩充性。而且, 不需要不断地®新建立与数据库的连接,因此提高了应用的性能,,
 
也可以将资源井亨应用于其他的资源,如套接字连接和线程。组件共亨仅仅意味着没 有必要为每个客户端提供专用的资源。可配置的典型参数包括容器线程、会话bean实例、 实体bean的缓存大小和数据库连接池的大小。需要适当地对所有这些参数进行配置,以 得到快速的响应时间和整体高的吞吐量。
 
16.4.5对Java虚拟机性能的依赖
 
在任何Java应用中,JVM都是调整性能的.个重要因素。因此.要开发和部署高性 能的EJB服务器端应用,就需要考虑-些JVM配置和性能调粮活动^
 
JVM堆的大小是一项重要的设置。堆是Java对象和闲置内存的存储库。当在堆中无JVM所需的足够内存时,将停止JVM中的所有执行。同时.个垃圾收集的箅法通过内存’ 释放不再需要的交间。这将明显地影响性能,因为应用代码在收集垃圾时中断了。因此’ 在EJB应用中.将不能执行任何服务器端的工作。
 
如果堆很大,垃圾收集就很少发生。然而,当进行垃圾收集时,将需耍很长的时间’ 很可能会中断正常的系统操作。垃圾收集可能会降低服务器的处玴速度(有时会使服务器 完全停止),从而使人觉得服务器太慢。
 
耍恰当地设定JVM堆的大小,有必要监视服务器的分页活动。分页需要很大的性能 开销。因此,应通过增加JVM堆的大小来匹配应用的需要,从而加以避免。另—个方法 是使用-gcverbose编译程序可选项观察垃圾收集器。如果增量垃圾收集是其中的可选项, 最好选中它。
 
16.5小 结
对Sun Microsystems的业务需求推动了 J2EE多层构架的创建。这些业务需求受到以 下因素的影响:从CORBA模型中总结出的经验教训:来自其他专有分布式编程模型(如 Microsoft的COM+)的竞争压力。J2EE采用了服务器端的组件框架.以构建企业强度服 务端 Java 应用,即 Enterprise JavaBean。
 
J2EE/EJB的规范在不断地扩展,当前已有的服务包括••事务、安全性、命名、持久性 和资源管理。这些服务能够使J2EE/EJB应用的程序员从低层的分布式细节中解脱出来, 从而将精力放在业务逻辑的开发上。J2EE/EJB通过使用-•种通用的可移棺的语言(Java) 并拥有组件间精确的契约,获得了可移植性-它还通过一些机制获得了性能和性能可扩充 性,这些机制包括:将应用分布给多个处理器(横向扩充)、无状态会话bean和资源池-尽管J2EE/EJB编程模型看上去十分简单,但-•些应用级的构架决策仍然需要认真制 定。必须对各种构架权衡进行分析和比较,以得出-个相对于应用质最猫求最优的设计方案。
 
16.6可进一步参阅的文献
 
有大歎关于J2EE/EJB构架和规范的信息可供参阅。其中,Sun Microsystems的主页 ( http://java.sun.com/J2ee)提供了容易理解的J2EE指南、各种白皮书以及J2EE/EJB的规 范.还有大釐关于J2EE构架和技术空间的活跃的论坛,包括•个由Middleware公司赞助 的论坛( http://wwwtheserverside.com)。
 
16.7讨论题
 
(1)    “消息驱动的bean”是对EJB组件模型2.0版本的-•个补充。这楚允许J2EE应用 异步处理消息的enterprise bean。您认为此类组件有哪些用途?您认为消息驱动的bean带 来了哪种可能的新的企业构架?
 
(2)    J2EE/EJB规范使用了很多技巧•它们实际上就是“使用仲裁者”战术的实现。尽 可能多地找到这些实例的不同实现。
 
(3)考虑一下第15章给出的CelsiusTech案例分析。对于实现该系统来说,J2EE/EJB 是否是-个好的基础结构选择,请对你给出的答案进行说明。
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/mongotea/p/11986418.html
EJB