Activiti与BPNM2.0规范之事件—来自程序lee的自我概述
这个标题有些许长,为什么这么起名字呢,原因就是Activiti是支持BPNM2.0的,所以就从以下几个方面认识一下这些个规范,或者说功能:启动与结束事件,顺序流,任务,网关,子流程,边界事件,中间事件,监听器。
今天就从事件开始说起。
要说事件,其又划分为启动事件,结束事件,边界事件,中间事件。
提前说一下,BPNM2.0中的异常,仅仅描述异常定义以及处理方式。
1.启动事件
启动事件负责一个人流程的开启,即每个流程总是以启动事件作为入口,在流程图中以细线圆形图案表示。
启动事件都是捕获型,也就是说,需要第三方触发后才可以启动,Activiti中可以通过调用API来触发启动事件runtimeService.startProcessInstance()
。
1.1空启动事件
startEvent标签中没有任务其他的元素定义,就是空启动事件,如下:
<startEvent id="startEvent" name="Start event" ></startEvent>
Activiti对其进行了一定的扩展:
activiti:formKey
:用来指定启动事件关联的表单文件,配置表单有两种方式:动态表单与外置表单(如何设置,还不会,待后续介绍,哈哈哈哈哈嗝~)
<startEvent id="startEvent" activti:formKey="apply.form" ></startEvent>
activiti:initiator
:用来记录启动流程的人的ID或名称
<startEvent id ="startEvevt" activiti:initiator="startUserID" ></startEvent>
1.2定时启动事件
常常用于一次性流程或者定期循环流程,在流程图中以细线圆形中间嵌套一个钟表标识。
<startEvent id="timerStartEvent" name="Timer start event for report process">
<timerEventDefinition> <!--定时事件的标签-->
<timeCycle>R1/2020-08-30T00:00/PM1M</timeCycle><!--每月启动一次-->
</timerEventDefinition>
</startEvent>
timeDate
:一次性定时启动,具体到某个日期
<timeDate>2020-08-30T00:00:00</timeDate> <!--在这个指定的日期启动一次流程-->
timeDuration
:设置一个时间,这个时间后启动流程
<timeDuration>PT10M</timeDuration> <!--上一个任务完成10分钟后启动流程-->
timeCycle
:周期性启动任务
<timeCycle>R3/PT10H</timeCycle> <!--循环三次,每次间隔10小时-->
1.3异常启动事件
异常启动事件可疑触发一个异常子流程,但是只能在另一个流程抛出异常结束事件时被触发,并且必须嵌套在一个事件的子流程中
。
异常启动事件也是捕获型,可以对应java中的catch,当然在BPNM2.0中需要两者的错误信息匹配才能决定是否触发异常启动事件。
在流程图中以细线圆形内嵌闪电符号表示。
<subProcess id="eventsubprocess1" name="Event sub Process" triggeredByEvent="true"> #1
<startEvent id="errorstartevent1" name="Error start">
<errorEventDefinition errorRef="AIA001"></errorEventDefinition> #2
</startEvent>
<scriptTask id="scripttask1" name="Script Task" scriptFormat="groovy"> #3
<script><![CDATA[out:println "catch an error;"]]></script>
</scriptTask>
<sequenceFlow id="flow3" name="" sourceRef="errorstartevent1" targetRef="scripttask1"></sequenceFlow>
<endEvent id="endevent3" name="End"></endEvent>
<sequenceFlow id="flow4" name="" sourceRef="scripttask1" targetRef="endevent3"> </sequenceFlow>
</subProcess>
#1处定义一个事件子流程
#2处是被事件子流程包裹的异常事件,异常代码为"AIA001"
#3处定义了一个触发异常启动事件,当捕捉到异常代码为"AIA001"时,触发此处
1.4消息启动事件
通过一个消息名称触发,从而启动一个流程实例,在流程图中以细线圆形内嵌空心信封表示。
<message id="reSendFile" name="重新发送文件" />
...
<startEvent id="messageStart">
<messageEventDefinition messageRef="reSendFile"></messageEventDefinition>
</startEvent>
2.结束事件
理论上结束事件与启动事件是成对存在的,但实际上结束事件可以没有。流程图中以粗线圆形表示。
结束事件总是抛出型的,当流程执行到结束事件时,会抛出一个执行结果(空结束事件例外)。
2.1空结束事件
空结束事件不抛出结果。
用于正常结束流程,也就是结束一条输出流。
<endEvent id="end" name="my end event" />
2.2异常结束事件
异常结束事件的错误代码不能为空,流程图中以粗线圆形内嵌闪电表示。
<endEvent id="endevent1" name="ErrorEnd"> #1
<errorEventDefinition errorRef="AIA-001"></errorEventDefinition> #2
</endEvent>
#1定义一个普通结束事件
#2表示一个异常事件,当遇到异常结束事件时,引擎查询定义为errorRef属性值
(编号)的异常启动事件,并触发。
2.3取消结束事件
可以取消一个事务子流程的执行,只能在子流程中使用,当有异常需要取消时,可以设置取消结束事件来中断流程的执行。流程图中以**粗线圆形内嵌一个’×’**表示。
可以与取消边界事件配合使用针对取消操作来做一个后续处理。
<endEvent id="myCancelEndEvent">
<cancelEventDefinition />
</endEvent>
2.4终止结束事件
可以终止一个流程实例的执行。
<endEvent id="terminateendevent1" name="TerminateEndEvent">
<terminateEventDefinition />
</endEvent>
3.边界事件
边界事件时绑定在活动上的捕获型事件,会一直监听所有处于运行中活动的某种事件的触发,再捕获到事件后中断活动,然后从边界事件类型的输出流继续执行。
一个活动只能绑定一个边界事件,通常都是通过属性attachedToRef
来指定附加到抛出边界事件的活动上。
<boundaryEvent id="boundary" attachedToRef="someActivity" cancelActivity="true|false">
<xxxxEventDefinition />
</boundaryEvent>
所有边界事件子类型均需要包含在boundaryEvent
标签中。
3.1定时器边界事件
与定时器启动事件类似,但应用场合不同,定时器边界事件需要附属再一个非自动任务(如用户任务)、调用活动、子流程上,在上游任务执行完成后开始倒计时预设的时间,时间到达后触发定时器边界事件的输出流(可以并行)。
流程图中以双细线圆形内嵌钟表表示。
<boundaryEvent id="boundarytimer1" cancelActivity="false" attachedToRef="hrAudit">
<timereventDefinition>
<timeDuration>P3D</timeDuration>
</timereventDefinition>
</boundaryEvent>
3.2异常边界事件
用来捕获嵌入子流程或调用活动抛出的异常,一旦异常抛出后被主流程序的异常边界事件捕获,那么嵌入的子流程或调用活动中的活动也会被中断执行。
流程图中以双细线圆形内嵌空心闪电表示。
<subProcess id="subprocess1" name="付款子流程">
...
<endEvent id="endevent2" name="ErrorEnd">
<errorEventDefinition errorRef="A001"></errorEventDefinition> #1-S
</endEvent> #1-E
</subProcess>
<boundaryEvent id="boundaryerror1" cancelActivity="false" #2-S
attachedToRef="subprocess1"> #2-1
<errorEventDefinition errorRef="A001" /> #2-E
</boundaryEvent>
#2-1指定到子流程subprocess1
,子流程中出现异常时,退出子流程并被附加在子流程的异常边界事件boundaryerror1
捕获,随后执行输出流任务。
#1处抛出一个异常结束事件,#2捕获一个异常结束事件。
3.3信号边界事件
可以捕捉流程执行过程(本流程和其他流程均可)中抛出的信号,可以附加在各种活动和子流程上。
信号抛出事件时全局的,即如果一个活动或者子流程上定义了多个信号边界事件并监听同一个信号,会被同时触发。
流程图中以双细线内嵌空心三角行表示。
<boundaryEvent id="boundary" attachedToRef="task" cancelActivity="true">
<signaleventdefinition signalRef="alterSignal" />
</boundaryEvent>
3.4取消边界事件
专门针对事务子流程所设立,并且只能与事务子流程结合使用,用来捕获子流程中抛出的取消事件。
流程图中以**双细线圆形内嵌空心’X’**表示。
<boundaryEvent id="boundary" attachedToRef="transaction" >
<cancelEventDefinition />
</boundaryEvent>
注意:
1.一个事务子流程只允许附加一个取消边界事件
2.如果事务流程中嵌套子流程,仅仅触发已经完成了的子流程的补偿事件
3.对于多实例的事务子流程,其中一个触发了取消事件,其他的实例同样会被触发取消边界事件
4.取消边界事件不需要设置attachedToRef属性,因为它总是中断取消边界事件附加任务后续活动的进行
3.5补偿边界事件
用于事务子流程中针对事务失败后的业务逻辑进行补偿,但是嵌入子流程不支持补偿边界事件。其输出流不是一个顺序流
,而是一个关联
,以虚线表示。
流程图中以双细线内嵌两个左三角表示。
<bounddary id="Event_1" name="捕获取消结束事件" attachedToRef="Task_2">
<compensateEventDefinition id="EventDef_1" />
</bounddary>
<association id="Association_1" sourceRef="Event_1" targetRef="Task_4"
associationDirection="One" />
<serviceTask id="Task_4" name="退回已扣金额" isForCompensation="true" />
compensateEventDefinition
表示一个补偿事件,association
关联两个对象。
isForcompensation
表示这是一个补偿型活动。
如果补偿边界事件附加的活动是多实例,抛出补偿事件时,每一个实例都会被触发边界事件。
4.中间事件
4.1中间捕获事件
根据事件的不同类型需要,使用不同的方式才能继续执行后续的输出流的活动
必须连接一个输入流和一个输出流,流程图中以空心表示。
<intermediateCatchEvent id="evvent1">
<xxxxEventDefinition />
</intermediateCatchEvent>
4.1.1定时器中间捕获事件
在一个特定的时间或指定间隔多长时间之后被触发,从而执行输出流后面的活动。
流程图中的图标与定时器边界事件一样,区分方式是再流程中的位置,在xml中描述为在intermediateCatchEvent
中包裹timerDuration
。
<intermediateCatchEvent id="timerintermediatecatchevent1" name="TimerCatchEvent">
<timerEventDefinition>
<timeDuration>PT5M</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
4.1.2信号中间捕获事件
用来捕捉当前流程或者其他流程抛出的信号事件,捕获的条件就是信号的ID一致。输出流流转到信号中间捕获事件后,流程就处于等待状态,有信号被抛出后,流程才能重新被激活,执行后续的活动。
当抛出的信号事件匹配到多个相同的信号捕捉事件时,每个匹配到的事件均会被执行,被称为广播式。
流程图中以双细线内嵌空心三角表示。
<intermediateCatchEvent id="signal">
<signalEventDefinition signalRef="doXxxxSignal" />
</intermediateCatchEvent>
4.1.3消息中间捕获事件
与信号中间捕获事件类似,但是消息中间捕获事件是一对一传递,流程图中以双细线圆形内嵌空心信封表示。
<intermediateCatchEvent id="messageCatch">
<messageEventDefinition messageRef="continueXxxx" />
</intermediateCatchEvent>
messageRef
用来定义一个消息名称
4.2中间抛出事件
用在一个任务完成后需要发送通知或者执行其他的系统任务的场景。
流程图中以实心图标表示。
<intermediateCatchEvent id="event1">
<xxxxEventDefinition />
</intermediateCatchEvent>
4.2.1空中间抛出事件
没有任何功能的事件,执行到空中间抛出事件时直接跳过。
流程图中以双层圆形表示。
<intermediateCatchEvent id="noneintermediatethrowevent1" name="NoneThrowEvent">
</intermediateCatchEvent>
虽然空中间抛出事件是一个空的任务,但是可以通过Activiti对大多数活动,事件添加的扩展功能而使其更有意义。
4.2.2信号中间抛出事件
可疑抛出一个信号,交给引擎传播信号事件。流程图中以双细线内嵌实心三角行表示。
<intermediateThrowEvent id="noneintermediatethrowevent1" name="SignalThrowEvent">
<signalEventDefinition signalRef="signal-001"></signalEventDefinition>
</intermediateThrowEvent>
默认是同步的,通过activiti:async
属性来设置是否同步,true为异步。