Activiti框架事件

作者: yingzong | 来源:发表于2017-10-13 17:20 被阅读501次
    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。

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

    相关文章

      网友评论

        本文标题:Activiti框架事件

        本文链接:https://www.haomeiwen.com/subject/glzzyxtx.html