发信人: yife()
整理人: majorsun(2001-12-13 18:22:32), 站内信件
|
kevin Yee
本文参考了SUN blueprint 模式站点中有关 Value Object(值对象)阐述[英文原文],向大家介绍一种 用粗粒度的数据对象传输 来 提高远程传输效率 的EJB配套 设计模式.该模式有效减轻了 以往翻复的 远程调用,减少了 网络的传输......
值对象 是使用 粗粒度的数据对象传输 来 提高远程传输效率。
实体 Bean 有时总是会有一大堆 属性变量,比如 用户的联系信息(城市,邮政编码,电话,Email等等),假设一下,如果 用户信息有15个属性,那需要声明 15个 getXXX 方法去 获取这些属性,当所有的用户信息被读取的时候,总共需要在CustomerEJB 中调用15个方法,这样加重了网络传输负担 和 容器的负载。
一种解决的方法是使用粗粒度数据对象来代表这些信息,我们把EJB 中的属性变量整和到一个 数据对象ContactInformation 中,之后该对象序列化后被传输到客户端调用,在那里被逆序列化后被客户解读,可以看出后来的解读过程是客户端对本地对象的操作,而不是对远程EJB 的操作,所以没有占用服务器的工作,减少了资源利用。
下图是操作EJB的属性变量,在使用值对象前后的对比
从图中我们可以看出后者 在读取 city, state zipcode等细粒度的变量时没有直接 操作 远程的 EJB ,而是一次性请求 EJB返回 一个 粗粒度的 CustomInfo对象 ,在本地 解析该 对象 返回细粒度的变量。这就是所谓的 值对象模式.
下图就是 值对象的结构图 :
需要注意的是 值对象 虽然是商业逻辑对象,但他只包含了如何解析 值对象 方法,如何构成这些信息 是EJB的工作.
应用值对象,我们应注意:
1.值对象 包含 一组私有变量 和一些获取这些变量相应的方法,他必须是可序列化的(要实现Serializable接口或者 提供方法 可以把变量 转化成可序列化 的对象,比如String),这样 EJB才能把它序列化。
2.值对象是只读的,他只是用于读取EJB的属性变量,我们不可能对他操作来改变 实体 EJB.不过我们可以创建一个新的值对象 ,把他作为远程EJB对象的一个创建参数 来更改 实体EJB的属性变量.这样做其实是把所有的改动一起传递给EJB,而不是象以往那样多次的调用远程方法来更改每一个属性.
3.考虑避免采用 过大的值对象 ,值对象本来就是为了减轻网络传输负担,所以需要 拆分 大的值对象.
4.在EJB2.0规范下使用值对象。在EJB2.0中 提出了依赖性值类(dependent value class),如果把实体Bean 看成是 数据库中一条(行)数据的话 ,依赖性值类就代表了一行数据 的 其中几列,这样 一个实体Bean 就可以表示成 几个 值对象,并且在 CMP 实体Bean 中需要 提供accessor (例如 getXXX) 和 mutator (例如 setXXX) 这样的方法来 读取和改写 值对象。很明显,accessor(getXXX)返回的是值对象 ,mutator(setXXX)把值对象作为参数 传入来改写 相应的数据.
范例代码:
我们看一下 在SUN的 java pet store范例中 做 实体 EJB数据 update 的 相应代码:
当从 一个 更新帐号信息的 jsp (editaccount.jsp) 提交了 更新请求 ,该请求由 web层的 AccountHandler 处理:
public class AccountHandler extends RequestHandlerSupport {
public EStoreEvent processRequest(HttpServletRequest request)
throws EStoreEventException {
// ...
String action = request.getParameter("action");
if (action == null) {
return null;
} else if (action.equals("createAccount")) {
return createNewAccountEvent(request);
} else if (action.equals("updateAccount")) {
return createUpdateAccountEvent(request);
// ...
}
}
createUpdateAccountEvent来把提交的信息封装成 contactInformation 值对象,并传送给 下一个处理
private EStoreEvent createUpdateAccountEvent(HttpServletRequest request) {
// ...
AccountEvent event = new AccountEvent();
// ...
ContactInformation contactInformation
= extractContactInformation(request);
// ...
event.setInfo(userId, contactInformation, explicitInformation);
// ...then Ejb will do with the contactInformation
}
}
EJB 层的 AccountHandler 来处理 更新操作,注意 CustomerEJB.changeContactInformation() 的参数 是 ContactInformation ,它由 ae.getContactInformation() 得到.
public class AccountHandler extends StateHandlerSupport {
public void perform(EStoreEvent event) throws EStoreEventException {
AccountEvent ae = (AccountEvent)event;
switch (ae.getActionType()) {
// ...
case AccountEvent.UPDATE_ACCOUNT: {
try {
CustomerHome home = EJBUtil.getCustomerHome();
Customer cust = home.create();
cust.changeContactInformation(ae.getContactInformation(),
ae.getUserId());
// ...
可以看出 以前 多次的 setxxx 的远程调用 被 现在一次 changeContactInformation() 替代了.
(图片源自java.sun.com)
source:
http://www.javadigest.net/index.php?newlang=zho
注:以上文章如果有不当之处,大家可以在阅读英文原文之后,给予指正 |
|