Activit的高级用例,会超越BPMN 2.0流程的范畴,使用Activiti高级功能需要有Activiti开发的明确目标和足够的Activiti开发经验
监听流程解析bpmn 2.0 xml文件需要被解析为Activiti内部模型,然后才能在Activiti引擎中运行.解析过程发生在发布流程或在内存中找不到对应流程的时候,这时会从数据库查询对应的xml
对于每个流程 ,BpmnParser类都会创建一个新的BpmnParse实例.这个实例会作为解析过程中的容器来使用
解析过程:
对于每个BPMN 2.0元素,引擎中都会有一个对应的org.activiti.engine.parse.BpmnParseHandler实例
解析器会保存一个BPMN 2.0元素与BpmnParseHandler实例的映射
默认Activiti使用BpmnParseHandler来处理所有支持的元素
同时也使用BpmnParseHandler来提供执行监听器,以支持流程历史
可以向Activiti引擎中添加自定义的org.activiti.engine.parse.BpmnParseHandler实例
经常使用的用例是把执行监听器添加到对应的环节,来处理一些事件队列.Activiti在内部就是这样进行历史处理的
要想添加这样的自定义处理器,需要为Activit增加配置:
<property> <list> <bean /> </list> </property> <property> <list> <bean /> <bean /> </list> </property>当自定义处理器内部逻辑对处理顺序有要求时需要考虑:
配置到preBpmnParseHandlers的BpmnParseHandler实例会添加在默认处理器的前面
配置到postBpmnParseHandlers的BpmnParseHandler实例会添加在默认处理器的后面
接口- org.activiti.engine.parse.BpmnParseHandler:
public interface BpmnParseHandler { Collection<Class>? extends BaseElement>> getHandledTypes(); void parse(BpmnParse bpmnParse, BaseElement element); }在BpmnParseHandler接口中:
getHandledTypes()方法会翻译这个解析器处理的所有类型的集合,这些都是BaseElement的子类,返回集合的泛型限制也说明了这一点
也可以继承AbstractBpmnParseHandler类并重写getHandledType()方法,这样就只需要返回一个类型,而不是一个集合
这个类也包含需要默认解析处理器所需要的方法
BpmnParseHandler实例只有在解析器访问到这个方法返回的类型时才会被调用
示例:
当BPMN 2.0 xml包含process元素时,就会执行executeParse方法中的逻辑
这是一个已经完成类型转换的方法,替换BpmnParseHandler接口中的parse方法
public class TestBPMNParseHandler extends AbstractBpmnParseHandler<Process> { protected Class<? extends BaseElement> getHandledType() { return Process.class; } protected void executeParse(BpmnParse bpmnParse, Process element) { .. } }注意:
在编写自定义解析处理器时,不要使用任何解析BPMN 2.0结构的内部类,这会导致出现问题很难定义
应该实现BpmnParseHandler接口或集成内部抽象类 org.activiti.engine.impl.bpmn.parser.handler.AbstractBpmnParseHandler
也可以替换默认的BpmnParseHandler实例,把解析BPMN 2.0元素替换为解析Activiti内部模型:
<property> <list> ... </list> </property>示例: 将所有任务强制设置为异步
public class CustomUserTaskBpmnParseHandler extends ServiceTaskParseHandler { protected void executeParse(BpmnParse bpmnParse, ServiceTask serviceTask) { // Do the regular stuff super.executeParse(bpmnParse, serviceTask); // Make always async ActivityImpl activity = findActivity(bpmnParse, serviceTask.getId()); activity.setAsync(true); } } 支持高并发的UUID的ID生成器在高并发的场景中,默认的ID生成器可能因为无法很快的获取新ID区域而导致异常
所有流程引擎都有一个ID生成器,默认的ID生成器会在数据库划取一块ID范围,其余引擎不能使用相同范围的ID
在引擎运行期间,当默认的ID生成器发现已经越过ID范围时,就会启动一个新事务来获得新范围.在极限的情况下,高负载会导致问题
对于大部分情况,默认ID生成已经足够:
默认的org.activiti.engine.impl.db.DbIdGenerator有一个idBlockSize属性,可以配置获取ID范围的大小,这样就可以改变获取ID的行为
另一个可以选用的默认ID生成器是org.activiti.engine.impl.persistence.StrongUuidGenerator:
会在本地生成一个唯一的UUID作为所有实体的标识
因为生成UUID不需要访问数据库,所以在高并发环境下的表现比较好
默认ID生成器的性能依赖于运行硬件
将UUID生成器配置到Activiti:
<property> <bean /> </property>