神刀安全网

Activiti框架事件

Activiti框架事件

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框架事件

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址