程序员android 开发程序员

Activiti框架事件

2017-10-13  本文已影响501人  yingzong
Activiti框架事件

Activiti事件主要包含两个概念:事件类型与事件定义。事件类型分为抛出型和捕获型,事件类型描述了事件发生的位置。对于捕获型事件,事件定义描述了事件被触发的时机;对于抛出型事件,事件定义描述了到达节点时发生的事件行为。

下面通过最常见的开始事件和结束事件找找感觉。

开始事件

开始事件指明了流程的起点,开始事件属于捕获型事件,当捕获到某种“信号”时发起一个新流程,这个“信号”可以是时间、消息或者是异常。

开始事件可以指定在2017-10-13T00:00:00发起流程:

<startEvent id="start" name="my start event">
    <timerEventDefinition>
        <timeDate>2017-10-13T00:00:00</timeDate>
    </timerEventDefinition>
</startEvent>

也可以指定收到某个消息时发起流程:

<definitions id="definitions"
    xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
    xmlns:activiti="http://activiti.org/bpmn"
    targetNamespace="Examples"
    xmlns:tns="Examples">

    <message id="newInvoice" name="newInvoiceMessage" />

    <process id="invoiceProcess">
        <startEvent id="messageStart" >
            <messageEventDefinition messageRef="newInvoice" />
        </startEvent>
        ...
    </process>

</definitions>

然后在代码中通过runtimeService.startProcessInstanceByMessage(String messageName)触发事件。

也可以不给开始事件指定任何事件定义(None Start Event):

<startEvent id="start" name="my start event" />

这种无事件定义的开始事件,只能通过runtimeService.startProcessInstanceByKey("someProcessKey")来发起。

结束事件

结束事件是流程的终点,结束事件属于抛出型事件,可以在到达结束事件节点时传播一个错误:

<endEvent id="myErrorEndEvent">
  <errorEventDefinition errorRef="myError" />
</endEvent>

也可以中断流程实例:

<endEvent id="myEndEvent >
    <terminateEventDefinition activiti:terminateAll="true"></terminateEventDefinition>
</endEvent>

代码实现

下面以消息开始事件和错误结束事件为例,看一下activiti框架的具体实现。

在流程图xml中,所有事件定义都以事件子节点的形式存在,而在Activiti框架中所有子节点的解析类都继承了BaseChildElementParser类。所以很快可以定位了消息事件定义和错误事件定义的解析器MessageEventDefinitionParserErrorEventDefinitionParser

从代码实现上,两个Parser并没有太大区别,都是解析xml内容,然后生成对应的EventDefinition,并添加到当前节点下:

((Event) parentElement).getEventDefinitions().add(eventDefinition);

在开始事件的handler处理步骤中,会获取解析出来的eventDefinition对象,调用对应的handler进行处理:

if (!startEvent.getEventDefinitions().isEmpty()) {
    EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
    if (eventDefinition instanceof TimerEventDefinition 
        || eventDefinition instanceof MessageEventDefinition
        || eventDefinition instanceof SignalEventDefinition) {
            bpmnParse.getBpmnParserHandlers().parseElement(bpmnParse, eventDefinition);
    } else {
        logger.warn("Unsupported event definition on start event", eventDefinition);
    }
}

消息事件定义对应handler是MessageEventDefinitionParseHandler,在handler中会为消息事件定义创建订阅关系,并最终在BpmnDeployer中以EventSubscriptionEntity实例形式落库。

当调用org.activiti.engine.impl.RuntimeServiceImpl#startProcessInstanceByMessage(java.lang.String)时,会从根据消息名称查询对应的EventSubscriptionEntity,获取其中的ProcessDefinitionId并发起流程。

结束事件的handler处理稍微有些区别,在结束事件的EndEventParseHandler中会判断是否包含事件定义和事件定义的类型:

if (eventDefinition instanceof org.activiti.bpmn.model.ErrorEventDefinition) {
    org.activiti.bpmn.model.ErrorEventDefinition errorDefinition = (org.activiti.bpmn.model.ErrorEventDefinition) eventDefinition;
    if (bpmnParse.getBpmnModel().containsErrorRef(errorDefinition.getErrorCode())) {
        String errorCode = bpmnParse.getBpmnModel().getErrors().get(errorDefinition.getErrorCode());
        if (StringUtils.isEmpty(errorCode)) {
            logger.warn("errorCode is required for an error event " + endEvent.getId());
        }
        endEventActivity.setProperty("type", "errorEndEvent");
        errorDefinition.setErrorCode(errorCode);
    }
    endEventActivity.setActivityBehavior(bpmnParse.getActivityBehaviorFactory().createErrorEndEventActivityBehavior(endEvent, errorDefinition));     
}

当事件定义是错误事件定义时,创建了ErrorEndEventActivityBehavior,并赋予了结束事件对应的ActivityImpl。

从代码实现上看,捕获型事件本质是一种订阅关系,订阅的对象可以是信号、消息、时间。而抛出型事件本质是一种特定的行为,行为可以是传播异常、终止流程等

上一篇下一篇

猜你喜欢

热点阅读