EJB设计

设计前的考虑:

         容器在集群环境下是否能够正常工作?能否提供负载均衡、故障转移(failover),以及重要数据备份的功能。
         EJB容器有很多工作要做:维护事务的完整性,管理bean实例及其实例池,实施安全角色,管理资源及资源池,协调分布式操作,集群,等等。
           数据库的锁机制、隔离级别以及如何在事务中管理资源?
           比如,事务执行时,游标会被打开,知道如何回收游标,才能安排事务的构成,确保事务成功执行。 

何时不用EJB

1EJB技术适合单线程环境不适合多线程环境。

2执行大量消耗CPU资源的操作的环境。

Java Persistence 的替代方案

当对速度的要求大过对事务或安全方面的要求时,JDBC是首选。

设计流程

识别业务实体
识别业务实体只是完整功能分析的一部分。还有设计用户界面,UML,以及非功能性需求(用户数,使用模式,等

等).

两个实体之间的基本关系:
1)is-a(继承)例子:类之间的继承,类和接口之间的实现
2)use-a(依赖)
3)has(聚合)   例子:车和轮胎间的基本聚合关系,Company类和Department类之间的组合聚合
4)is associated with(较弱的关联,不是父子)
实义动词
UML

并非所有的业务实体最终都会成为EJB或entity bean,下一步就是要确认哪些实体应该成为EJB或entity bean。

在本地或通过RMI对session bean进行调用,采用的都是同步机制。MDB是异步方式。

指导原则1
如果给定的某个session bean有个方法,该方法几乎总是在另一个session bean 的函数上下文中被调用,那么

或者合并这两个session bean,或者将方法移至另一个bean中。
指导原则2
MDB的命名
一条经验法则是:将MDB所接受到的消息的类别描述与Listener字样组合在一起。
通常可以用Processor来代替Listener,但是它不够明确,容易造成混淆。
5种消息类型(ObejctMessage,TextMessage,BytesMessage、MapMessage、StreamMessage)
在明确是基于Java技术的系统之间使用ObejctMessage来传递消息。
在可能采用非Java技术的系统之间使用TextMessage,它是最为通用的消息类型。

高难度的决策
Stateful Session Bean与Stateless Session Bean
当使用集群时,stateful session bean 的性能问题也需要考虑。经过集群处理的stateful session bean,其

状态必须被复制到集群中的其他节点。这样,当某台机器出现故障时,客户端请求才可能被成功转移。这样的复

制行为可能会带来大量的网络流量和CPU负载。通常而言,我们应该将分布式系统尽可能设计成无状态的。但是

,如果客户端需要和应用系统进行有状态的会话,那么你就需要在应用系统的某些地方承担状态复制的开销(无

论是在web层还是EJB层)。

Local interface与Remote interface
若非必要,切记不要使用远程接口。将EJB置于分布式环境下会多一层不必要的复杂性。我们会遇到一些复杂而

又棘手的问题,比如系统因为远程调用而损失了高性能和稳定性。一个最为复杂的问题是,远程接口(及其实现)

通常是难以修改的,因为它们会被其他应用系统所使用,而这些系统可能会抵制新的变化。

   让我们的session bean同时实现远程接口和本地接口是一个不错的主意。虽然这么做使得构建和维护的代码

量会稍多一些,但是在运行于应用服务器内部的代码中(例如servlet或JSP),使用本地接口不失为一个良策。小

小的重复带来的好处是避免了远程接口的使用。


减少数据库访问次数
EJB应用中最大的瓶颈通常是数据库。它往往是高度竞争的资源,需要进行大量的优化。
有很多数据库调优的方法,我们只讨论两种:缓存技术和减少数据库访问次数。

缓存通常只作用于EntityManager的find()和getReference()方法,这是因为缓存通常只由一个简单的map构成,

并且是用主键作为标志符的。EJB QL查询通常不会被缓存,但有些厂商也提供了这方面的缓存能力。(如何考察

应用服务器有没有这方面的能力及能力大小?)

有关缓存的一些常识性原则包括:
为经常被访问的实体预留较大的缓存空间;
为很少被访问的实体预留很少的缓存空间,或者根本不用缓存;
不为经常更新的实体提供缓存。如果仅在一台服务器上并不是问题,但在集群环境下则会使性能很快下降。这是由于执行

更新操作的服务器必须向系统中的其他节点发送网络消息,以确保远程缓存始终是最新的。

合并查询
实体的FetchType依然是LAZY。
Query query = entityManager.createQuery("FROM Cruise c LEFT FETCH JOIN c.reservations where c.id =1");
代替
Cruise cruise = entityManager.find(Cruise.class,1);

减少更新
entityManager.setFlushMode(FlushModeType.COMMIT);

设计细化
直至类和方法级。

可能会在应用系统中发现如下问题:
自定义的JMS监听器访问了session bean。
Session bean 为个别数据提供了getter/setter方法。
Entity bean包含了复杂的业务逻辑。
上述错误对系统的影响可能很小(需要建立和维护一两个额外的类),但也可能会导致EJB不能正常工作或无法

维护。


缩小事务的范围
当你对EJB,尤其是session bean进行设计细化时,请确保事务范围尽可能小。此处所谓的范围,是指执行操作

的次数及所用组件的数量。
找出应用系统中的复杂任务流。重点关注单个事务中是否出现如下情况:对多个EJB进行遍历,对数据进行聚集

,或EJB的链式调用(一个EJB调用另一个EJB,而另一个EJB又调用其他EJB,如此继续。)事务的范围会被传播

到调用链上涉及的所有EJB,那些在部署描述文件中指定了NotSupported或RequiresNew事务属性的EJB方法除外

异常
异常设计的几个基本步骤。
1.识别业务异常。
不要将异常当作if-then语句或其他形式的流转控制大量使用。
业务异常几乎可以直接从业务需求中被提取出来。识别诀窍:明确业务异常所关注的是错误情况。有些开发者使

用异常来控制用户交互,这是错误的。例如,如果系统中一次针对信息的查询没有找到任何匹配的结果,那么最

好是返回一个空的集合,而不是抛出一个异常。异常应该是留做错误处理之用的,我们应该采用其他机制类控制

用户交互。

2.为业务异常设计层次结构(此类信息对精确调整数据库容量也是有必要的。)。
3.明确每个业务异常的回滚行为,并适当运用@ApplicationException和<application-exception>.
4.明确每个业务异常应该是"unchecked"的还是checked。
5.声明或包装会引起回滚的子系统异常或第三方系统的异常。
设计异常层次结构
1.始终将通用的异常功能包含在一个基类中(可能是抽象类)。我们可以将其命名为AbstractException。
2.AbstractException还应该包含用于传递错误编码的相关代码和属性,至少有两中类型的错误编码:一种是用

于通知用户的。一种是用于通知开发的。这些编码应该对应于ResourceBundle或其他文本本地化机制中的某些项

。请使用简洁明了的文本编码(例如AVAILABLE_INVENTORY_EXCEEDED),不要使用数字或其他难于理解的编码。
3.为每个主要的包建立AbstractException的子类,例如InventoryException,GuestException。
4.可以根据需要对某个包中的异常进行子类化,专门指示某种错误情形。CabinSoldOutException、

DeckSoldOutException,以及CruiseSoldOutException都可能是InventoryException的子类。可以根据需要建立

足够多的子类。
5.在设计EJB的接口时,首先列出每个方法可能会抛出的所有异常。其中一条经验法则是:如果一个方法可能会

抛出三个或者三个以上的异常,而这些异常都是同一包级异常的子类,则将他们替换为包级异常。

确定回滚异常
如果在异常层次结构的每一处都使用了@ApplicationException,那么你就可以在运行时,在不必要知道具体异

常类型的前提下,对这一注解元数据进行检查,以决定事务是否回滚。RuntimeException或RemoteException无

需标注@ApplicationException。利用@ApplicationException类标志回滚,这种做法是值得推荐的

checked exception与unchecked exception
只有当你确实需要调用方对异常进行处理时,才需要使用checked exception。即使你使用的主要是unchecked

exception,将unchecked exception 写入方法签名的throws 子句中也是一个很好的习惯。
有类checkd exception需要我们加以特别处理,我们称其为子系统异常。例如IOException,JMSException,

SQLException。如果子系统异常不可恢复,或者无法重试,那就不必将其置于方法的throws子句中了。在这种情

况下,应该将异常捕获并包装成一个EJBException或合适的业务异常。


工具类
工具类是很难准确定义的,因为它们包括了通用的数据持有类(即数据封装类),以及非数据类(即方法类)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值