利用CMP2和XML处理惩罚动态数值工具
当前位置:以往代写 > JAVA 教程 >利用CMP2和XML处理惩罚动态数值工具
2019-06-14

利用CMP2和XML处理惩罚动态数值工具

利用CMP2和XML处理惩罚动态数值工具

副标题#e#

在EJB 2.0局部引用和容器打点干系呈现之前,凡是把实体EJB用于模子粗粒度域工具。这主要是由于与长途通信有干系统开销并阻止了细粒度会见企业层的客户层工具。粗粒度设计的机能通过实现数值工具而促进改进,压缩所有的数据也就是说在客户层和企业层之间通报数据。利用有大量域工具的巨大系统,纵然这么样能提供一个最高级的和高度执行设计,这个设计导致在系统内呈现过多的数值工具。这同样也建设在企业层和客户层之间的细密毗连。同样,在EJB呈现之间,bean提供者不得不明晰地提供用于维护域工具之间联接的措施。在一个有在域工具之间的巨大干系的环境中,数值工具的设计变得很巨大。在利用EJB开拓企业应用措施的进程中,容器打点干系和局部引用的呈现开启了令人欢快的新途径。在本文中,我将带你利用EJB 2.0的强概略领连同bean组件和JAXP建设动态的基于数据布局的XML,可以在你的企业层和表示层之间通报信息。

从企业层到客户层通报数据的进程中利用XML,可以辅佐你实此刻的应用措施中的多种宽松毗连;然而,当你把新的域工具添加到实体型中时,你大概需要添加用于建设新DOM构架的类来添加该实体。在文中,我们将开拓一个框架来动态地遍历容器打点和给定的局部EJB有关的域,而且建设一个可以在应用措施的多个层之间通报的XML件。这个要领将有以下利益∶

在企业层和客户层之间促进宽松毗连。

便于打点域工具之间干系。

从系统中撤除巨大数值工具因为XML是由动态地遍历CMP和CMR域发生的,当它们添加新工具到域模子中时,bean提供者不必建设新的用来建设新的DOM构架的工具类。

EJB 2.0局部引用促进会见bean组件;bean组件与局部引用团结可以含于与其他的被容器打点的bean的干系。举例来说,在一个辅佐系统中,UserEJB可以有与ServiceRequestEJB的一到多双向干系和与ProductEJB的一到一的单向接洽以及与ServiceRequestHistoryEJB的一到的双向干系。UserEJB同时可以有与PhoneEJB一到多的双向干系。这样,利用EJB 2.0局部引用和容器打点干系,你可以设计一套巨大的有关体。容器打点耐久性和干系域是在bean类中利用抽象存取措施要领定的。用于干系域的存取措施要领要么返回一个荟萃要么返回界说这个系的bean的本机接口,这还取决于这个干系集的容量。这些存取措施法可以通过bean组件的本机接口展示。EJB 2.0的深入研究超出了本文范畴,请参阅EJB 2.0的类型。

一个效率高的设计模式应该通过外观组件展示你的应用措施的利用案例而且禁绝从客户层中直接会见实体组件。回到我们的辅佐系统的例子中来,个中的一个利用案例是取得给定用户的具体资料。外部组件可以查找需要的用户实体组件,而且通过容器打点耐久性与干系域取得所需数据并把它返回表示层。

用于数据传送工具的一个显而易见的选择就是简朴的Java bean。UserBean大概有暗示耐久性与干系域的属性。这种干系域要么是java.util.Collection要么是其他的取决于这种干系的bean组件。UserBean大概有ServiceRequestBean和PhoneBean集。ServiceRequestBean大概有一个ProductBean和很多ServiceRequestHistory bean组件。另外,这些bean组件还大概尚有简朴的String可能表示容器打点耐久性域的根基属性。这个选择的主要的倒霉之处就是使你的实体模子越发巨大,使你的数据传送工具bean条理越发巨大,还将在你的处事(企业)层和消费(表示)层之间建设细密毗连。研究一下这个干系的巨大的条理,一个更好的选择是利用XML DOM工具作为数据传送工具。你的组件将发生oeg.w3c.dom.Document工具范例而且你的表示组件利用XML的JSP自界说标志和XSLT文件来“消费”它们。

此刻,下一个问题是∶怎么从CMP局部bean引用中建设XML文件?我们可以利用一个基于用于建设差异的范例的DOM组件的要领的工场;然而,这将建设过多的“工厂”组件,而且你大概需要添加新的"工厂"组件作为你的实体模子扩展。我们需要的是一个可以利用实体局部工具,引导容器打点干系和建设动态DOM构架的公用措施。这个公用措施将认真在双向干系中轮回引用,以制止无限的轮回和深入导航干系元素。


#p#副标题#e#

接下来我们将演示一个可以提供这个成果的公用措施类。

package ws.business.service.util;
导入JAXP类。
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
导入DOM类
import org.w3c.dom.Document;
import org.w3c.dom.Element;
导入EJB类
import javax.ejb.EJBLocalObject;
导入Collection类。
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
导入bean内省类。<0}
import java.beans.Introspector;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.beans.IntrospectionException;
导入reflection类
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class DOMGenerator {
生成的文件
private Document doc;
用户界说的深度∶
private int drillDownDepth;
存储轮回引用的私有实例变量∶
private ArrayList _circularRef = new ArrayList();
存储当前深度的私有实例变量∶
private int _currentDepth;
要领getEJBLocalHome,getLocalHandle,getClass和getPrimaryKey不必
被处理惩罚。
private static String RESERVED =
"EJBLocalHome^localHandle^class^primaryKey";
   public DOMGenerator(String docElementName, int drillDownDepth) {
   try {
利用尺度JAXP挪用来建设一个DOM并把它存储为一个实例变量。
DocumentBuilderFactory fact =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = fact.newDocumentBuilder();
doc = builder.newDocument();
}catch(ParserConfigurationException ex) {
throw new RuntimeChainedException(ex);
}
存储drilldown深度。
this.drillDownDepth = drillDownDepth;
以用户界说的名称建设文件元素。
doc.appendChild(doc.createElement(docElementName));
   }
建设通报DOM的局部引用的要领。
   public Document getDOM(EJBLocalObject local) {
   try {
挪用把容器打点耐久性与干系域填充到元素中以便通报局部引用的方
法。
populateElement(doc.getDocumentElement(), local);
返回DOM。
return doc;
}catch(IntrospectionException ex) {
throw new RuntimeException(ex.getMessage());
   }catch(IllegalAccessException ex) {
throw new RuntimeException(ex.getMessage());
}catch(InvocationTargetException ex) {
throw new RuntimeException(ex.getMessage());
}
   }
   private void populateElement(Element parent, EJBLocalObject local)
throws
IntrospectionException, IllegalAccessException,
InvocationTargetException
{
   把当前的局部引用添加到毗连引用列表中。
_circularRef.add(local);
增加当前的drilldown深度。
_currentDepth++;
取恰当前的局部引用的bean组件信息。
BeanInfo info = Introspector.getBeanInfo(local.getClass());
取得属性描写信息列表并反复数组。
PropertyDescriptor properties[] = info.getPropertyDescriptors();
   for(int i = 0;i < properties.length;i++) {
取得属性读取要领。
Method propReadMethod = properties[i].getReadMethod();
取得属性名称。
String propName = properties[i].getName();
利用映射取得属性值。
Object prop = propReadMethod.invoke(local, null);
跳过保存属性。
if(RESERVED.indexOf(propName) >= 0)
continue;
   try {
实验把属性强制转化为EJB局部引用。请留意你不能利用instanceof,因
为从容器到容器利用instanceof,实现大概有差别。
EJBLocalObject locProp = (EJBLocalObject)prop;
假如局部引用已经在毗连引用的列表中可用可能当前的drilldown深度
已经大于配置的drilldown深度那么就跳出处理惩罚进程。
if(isCircularRef(locProp) || _currentDepth >=
drillDownDepth)
continue;
由属性建设一个元素。
Element child = doc.createElement(propName);
populateElement(child, locProp);
把新建设的子元素添加到父元素中。
parent.appendChild(child);
   }catch(ClassCastException ex1) {
   假如抛出一个ClassCastException,就要试着把属性强制转换成Collection
局部引用范例。请留意你不能利用instanceof,因为从容器到容器利用
instanceof,实现大概有差别。
try {
   Collection colProp = (Collection)prop;
   假如当前的drilldown深度大于配置的drilldown深度,跳出处理惩罚。
if(_currentDepth >= drillDownDepth) continue;
建设一个压缩collection的子元素。
Element child = doc.createElement(propName);
Iterator it = colProp.iterator();
   while(it.hasNext()) {
   获得collection中的每个局部引用。
EJBLocalObject locProp =
(EJBLocalObject)it.next();
假如局部引用已经在毗连引用的列表中可用可能当前的drilldown深度
已经大于配置的drilldown深度那么就跳出处理惩罚进程。
if(isCircularRef(locProp)) continue;
建设一个能包括用于这个collection中当前的局部引用耐久性与干系信
息的元素,然后把它添加到表示这个collection的元素中。
Element grandChild =
doc.createElement(propName +
"-child");
   child.appendChild(grandChild);
   populateElement(grandChild, locProp);
   }
parent.appendChild(child);
   }catch(ClassCastException ex2) {
   假如抛出一个ClassCastException的话,属性是一个耐久性域而且要把它
的值添加为当前节点的值。
parent.setAttribute(propName, prop.toString());
}
   }
   }
从列表中移走当前的局部引用。
_circularRef.remove(local);
递减当前的drilldown深度。
_currentDepth--;
   }
这是一个公用措施要领,用来查抄一个引用是否已经在毗连引用列表
中。
private boolean isCircularRef(EJBLocalObject local) {
   Iterator it = _circularRef.iterator();
while(it.hasNext())
if(local.isIdentical((EJBLocalObject)it.next())) return true;
return false;
   }
   }

#p#副标题#e#

下面的代码片段演示如何利用这个类:

#p#分页标题#e#

User local = userHome.findByPrimaryKey("1");
return new DOMGenerator("user", 4).getDOM(local);
下面演示的这段生成的DOM取决于你的实体模子∶
<?xml version="1.0" encoding="UTF-8"?>
<user firstName="Wayne" id="1" lastName="Zheng">
   <requests>
quests-child description="Outlook not working" id="2"
status="P">
<product description="Install Laptop" id="1"
name="SVC01"/>
</requests-child>
<requests-child description="PC not booting" id="1" status="O">
<histories>
<histories-child description="Informtion requested"
id="2"
loggedAt="2002-4-7 12:12:12.0"/>
<histories-child description="Request logged" id="1"
loggedAt="2000-4-7 00:00:00.0"/>
</histories>
<product description="Install Laptop" id="1"
name="SVC01"/>
</requests-child>
</requests>
   <phones>
<phones-child id="2" number="0771 8210586" type="M"/>
<phones-child id="1" number="01908 251575" type="W"/>
</phones>
   </user>

#p#分页标题#e#

在本文中,我们具体研究了一个模子用于在一个J2EE应用措施的企层和表示层之间通报巨大数据。表示层可以交付XML数据,这些数据在企业层上生成的,被利用XSLT可能XML JSP自界说标志交付到客设备上。

当你添加新的界说到你的域模子中的时候,你独一需要做的工作就是利用风雅局部实体bean界说,然后利用容器打点干系界说干系。DOM生成措施提供一个一般的要领生成动态的XML文件。

然而,就象任何其他的设计方案,这个要领也有它的缺点。一个明明的方面就是开拓人员常常担忧基于XML的数值工具的机能。在一台1GHz CPU, 256MB内存,操纵系统为Windows ME的呆板中,运行应用软件处事器(WLS 6.1)和数据库处事器,上述对一千条记载的记录集的操纵以及处理惩罚多元接洽用了不到0.5秒钟。第二个明明的方面就是范例安详性。因为XML提供了数据抽象化的第一流别,属性的结点值和文本节点老是被当做字符串。假如你规划在从企业层上检索返来的数值工具长举办进一步的事务操纵的话,最好就利用Java bean组件。然而,XML模式提供了一个成果强大的机制,用于增强XML文件的范例安详性。在两种环境下都要利用局部实体工具作为域工具。

这个要领最大的缺点就是没有模子化基于XML数据的明晰界说的要领。我还没有瞥见过任何模子化利用XML的域工具干系的UML注释可能通用的类型界说。

    关键字:

在线提交作业