Activiti权威指南
上QQ阅读APP看书,第一时间看更新

4.1 文档解析基础

4.1.1 文档解析模型

关于XML文档解析技术,目前经常使用的有DOM、SAX、DOM4J等,这些解析方式从模型上可以划分为如下两种:DOM(文档对象)模型和流模型,下面对比这两种模型的优缺点。

(1)DOM模型。

优点:文档解析的时候允许客户端编辑和更新XML文档内容,并可随机访问文档中定义的元素数据。

缺点:文档解析的时候会将需要解析的XML文档内容一次性加载到内存,进而映射为Document对象中的树形结构,基于该特性可以知道该方式解析大文件的时候,内存占用率大,元素遍历查找慢,很容易造成性能问题。

(2)流模型。

优点:该方式解析文档的时候,每一次操作只会将需要解析的节点放置到内存中,从头部开始,读取一段,处理一段,这样就解决了文档对象模型可能引发的性能问题,该方式内存占用率少,性能大幅提升。

缺点:该方式解析文档的时候文档是只读的,不可以编辑,文件流只能前进不能回退。

4.1.2 Activiti文档解析技术选型演变

基于上面所说的两种解析模型,因为Activiti将流程文档完全交给客户端定义和使用,所以最终生成的XML文件大小完全由用户决定,是不可控因素之一,软件架构设计之初应该尽量屏蔽这种不可控的风险,所以Activiti最终选择流模型方式进行文档解析工作。

流模型常用的技术有SAX和STAX两种,SAX使用的是推模型,STAX使用的是拉模型。

(1)推模型。

推模型:SAX处理方式,是一种事件驱动机制,文档解析的时候,每当发现一个元素节点就会触发相应的事件,因此客户端需要编写监听触发事件的处理程序,使用该方式解析文档无疑增加了客户端操作的复杂度,使用起来比较麻烦,不灵活。

(2)拉模型。

拉模型:STAX处理方式,文档解析时客户端可以定制自己感兴趣的节点主动从读取器(Reader)中进行拉取,选择性的处理节点事件。对比推模型,该方式灵活性大大提高。

基于上面罗列的流模型解决方案,Activiti最终选用STAX方式解析流程文档。STAX提供了两套处理XML的API,它们分别是基于指针的API和基于迭代器的API。两者解析原理类似,下面讲解的文档解析实战主要是基于指针的API,如果对基于迭代器的API操作感兴趣可以自行学习。

注意

Activiti在5.12.1版本中开始使用STAX方式解析流程文档,之前版本使用的是SAX方式解析流程文档。

4.1.3 文档解析实战

为了便于理解,可以把STAX模型理解为一个不可回流的流水管道,该管道主要用来存储流程文档定义信息,读取器可以理解为水龙头,每次读取器读取文档内容的时候,客户端可以对读取的流进行处理,也可以不理会。下面创建一个名为stax.xml的文档用于测试,该文档的内容如代码清单4-1所示。

代码清单4-1 stax.xml

在上述代码中,定义了父元素process和两个子元素userTask、endEvent。流程文档定义完毕,再写一个解析类对stax.xml内容进行解析,该类的相关定义如代码清单4-2所示。

代码清单4-2 StaxTest.java

下面对上述代码中STAX技术解析流程文档的处理逻辑加以总结:第4行使用XMLInputFactory类的newInstance方法创建XMLInputFactory实例对象,第6~7行获取XML文档中的数据流,第9行根据获取到的数据流构造读取器Reader实例对象,第11行调用xif对象的createXMLStreamReader方法,并传入该方法需要的读取器构造XMLStreamReader实例对象,第13行中的event变量值表示当前指针所指向的标记或者事件的类型,开发人员可以根据标记或者事件类型定制感兴趣的部分进行解析处理。Event可取值均定义在XMLStreamConstants类中,如表4-1所示。

表4-1 事件类型的名称、含义和值

STAX方式解析XML文档的核心点在于程序可以根据当前的标记或事件类型做出相应的处理。深入理解上面罗列的每一个event值的具体含义后,就会发现使用STAX技术解析XML文档是非常简单的一件事情,因为它的用法和Java迭代器(Iterator)是一样的,至此STAX技术解析XML文档的过程已经分析讲解完毕。