XML网格示例
1. 场景描述
本文的背景信息即是通过网格存储服务请求负载数据以实现多步业务过程的索物标签模式。但是我们的示例的主要目标是展示如何在网格中存储大型XML文档并对其进行操作(然后才能使用索物标签模式对其进行处理)。
示例场景如下:一个大型XML文档需要被多个服务处理。无需对文档进行反串行化、解析、处理、再串行化整个文档,只是把文档分成小块,转换成Java对象并储存在应用网格中。这个操作将由服务链中的第一个服务进行,或者由第一个服务之前的辅助服务完成。从服务向服务传递的是小得多的XML消息--"索物标签,其中包括读取应用网格中的数据所需的关键字。
此外,并不是只有以序列化的方式执行多个服务的时候这个模式才有用。也可以是每天填充一次但是一直要被各个服务操作或被用户通过门户应用查询的诸如汽车租赁利率或航班数据等参考数据。
2. 拆分XML
我们使用STAX解析器将XML文档分解成多个组成部分。因为STAX开始的时候仍会具体化对象树,所以我们人为地寻找诸多重复元素中的第一个。如果XML在一个称为"项类"的容器节点中含有多个"项",解析器就从"项"开始以避免具体化整个"项类"树。列表1是这个操作的关键部分。
列表1:通过STAX解析分解XML流并提取重复的元素
EventFilter filter = new EventFilter() {
public boolean accept(XMLEvent event) {
//first off, we need a startElement
if (!event.isStartElement()) return false;
StartElement e = (StartElement)event;
//more importantly, it must be the first "item"
if ((e.getName().getLocalPart()).equals("item"))
return true;
return false;
}
};
然后我们使用JAXB将单个XML元素转换为Java对象。JAXB允许XML的POJO呈现,这使其串行化比其它XML-Java技术更简单。在运行这段代码之前,我们先用Eclipse XJC插件从XML Schema中生成了JAXB类。列表2显示了这个XML流循环的开始部分,其每一次循环都将生成一个JAXB对象。
列表2:通过JAXB调用将XML元素转换为Java 对象
while (xmlfer.peek() != null) {
JAXBElement<Item> o = (JAXBElement<Item>)um.unmarshal(xmler);
if (o.getValue() instanceof Item) {
Item ii = (Item) o.getValue();
…
}
一旦我们有了指向"项"的参数(JAXB对象),我们就把它放到应用网格中。在本例中,我们使用了可以模拟(Java和C++)Java Map API和(.NET)Dictionary接口的Oracle Coherence(见列表3)。
列表3:使用Map API将Java对象存储到应用网格
//put into grid
String itemKey = ii.getPartNum();
itemCache.put(itemKey, ii);