Events 事件
1, 事件用于对发生在流程生命周期的事情进行建模。事件总是被形象成一个圆圈。在BPMN 2.0 中,存在两种主要的事件类型:捕获事件和抛出事件。
捕获:流程执行到该事件时,会等待事件触发。事件触发类型由内部图标或XML中的类型声明来定义。捕获事件视觉上可以通过里面没有填充的内部图标与抛出事件进行区分(也就是说,图标是白色的)。
抛出:流程执行到该事件时,事件就会被触发。该事件触发的类型由内部图标或XML中的类型声明来定义。抛出事件视觉上可以通过内部图标与抛出的事件进行区分,抛出事件的图标使用黑色填充。
Timer Event Definitions 定时器事件
定时器事件是被定义的定时器触发的事件。可以作为启动事件、中间事件或边界事件来使用。
定时器的定义只能有以下的一个元素:
timeData:该格式以ISO 8601格式指定了触发事件的确定时间(译注,即,在确定时刻触发定时器事件)。示例:
<timerEventDefinition> <timeDate>2011-03-11T12:13:14</timeDate> </timerEventDefinition>
timeDuration:指定定时器事件在触发前运行多长时间,timeDuration可以作为timerEventDuration的子元素来指定。使用的格式是ISO 8601格式(这是BPMN 2.0规范所要求的)。示例(间隔10天 ):
<timerEventDefinition> <timeDuration>P10D</tim </timerEventDefinition>
timeCycle:指定循环的时间间隔(译注,即,每隔多长时间执行一次循环),这对于周期性的启动流程或者给过期的用户任务发送提示是很有帮助的。时间循环元素可以使用两种格式来指定。首先是循环次数的持续的格式,这是ISO 8601所规定的。示例(循环3次,每次循环持续10小时)
<timerEventDefinition> <timeCycle>R3/PT10H</timeCycle> </timerEventDefinition>
此外,你也可以使用cron表达式来指定循环次数,下面的示例展示了每5分钟触发一次
0 0/5 * * * ?
循环持续的次数更适合处理那些在时间上相对于某个特定的时间点(如,用户任务开始时)来计算的相对定时器,
然而cron表达式可以处理绝对定时器,这对于timer start events是特别有用的。
你可以在定义定时器事件时使用表达式,这样你就可以基于流程变量来影响定时器的定义。流程变量必须包含恰当定时
器类型的ISO 8601 字符串(或循环类型cron)。
<boundaryEvent id="escalationTimer" cancelActivity="true" attachedToRef="firstLineSupport"> <timerEventDefinition> <timeDuration>${duration}</timeDuration> </timerEventDefinition> </boundaryEvent>
注意:只有在开启作业执行器时,定时器事件才能被触发(即,需要在activiti.cfg.xml中将jobExecutorActivat 设置为true),
因为默认job executor 是被禁用的。
Start Events 启动事件
启动事件表示流程的开始。定义了流程如何被启动的启动事件类型(当收到消息、特定的时间间隔、等等,启动流程)是以一个小图标来形象表示事件的。在XML表示中,类型是由子元素的声明给出的。启动事件总是捕获型的:从概念上讲,该事件(任何时候)会一直等待直到触发发生。
启动事件中,可以指定以下Activiti 所特有的属性:
formKey:指向一个用户必须在启动新流程实例时填写的表单模板。更多信息见表单一节。示例:
<startEvent id="request"activiti:formKey="org/activiti/examples/taskforms/request.form"/>
initiator:指明在流程启动时存储被认证的用户id 的变量名。示例:
<startEvent id="request"activiti:initiator="initiator"/>
被认证的用户必须必须在tye-finally块中使用方法IdentityService.setAuthenticatedUserId(String)来设置,如下
try{
identityService.setAuthenticatedUserId("bono");
runtimeService.startProcessInstanceByKey("someProcessKey");
}finally{
identityService.setAuthenticatedUserId(null);
}
None Start Event 空启动事件
从技术上讲,‘空’启动事件意味着不给启动流程实例指定触发器。空启动事件使用在通过调用startProcessInstanceByXXX方法启动流程实例的时候。
ProcessInstance processInstance= runtimeService.startProcessInstanceByXXX();
注意:子流程总是有一个空启动事件。
空启动事件被形象化成不带内图标的圆(即,没有触发器类型)。
空启动事件的XML表示是不带子元素的普通启动事件声明(其它启动事件类型都有声明类型的子元素)。
<startEventid="start"name="my start event"/>
Timer Start Event 定时器启动事件
定时器启动事件用于在给定的时间点创建流程实例。它可以用在只启动一次的流程中,也可以用在特定时间间隔下启动的流程。
定时器启动事件被形象化成带有时钟内图标的圆。
从2011年3月11日12:13开始,流程将启动4次,每次间隔5分钟。
<startEvent id="theStart">
<timerEventDefinition>
<timeCycle>R4/2011-03-11T12:13/PT5M</timeCycle>
</timerEventDefinition>
</startEvent>
流程将在选定的时间上启动一次
<startEventid="theStart">
<timerEventDefinition>
<timeDate>2011-03-11T12:13:14</timeDate>
</timerEventDefinition>
</startEvent>
End Events
终止事件表明流程或子流程(的执行路径)的结束。终止事件总是抛出型的。这意味着当流程执行到终止事件时,有一个结果会被抛出。结果的类型是以事件的内部黑色图标来表示的。XML表示中,类型是由子元素的声明给出的。
空终止事件
‘空’终止事件意味着不指定当达到该事件时抛出的结果。这样,流程引擎除了结束当前的执行路径不会再执行任何其它操
作。
空终止事件的XML表示为没有子元素的普通的终止事件的声明(其它终止事件类型都有声明类型的子元素)。
<endEventid="end"name="my end event"/>
Error End Event
当流程执行到异常终止事件时,会结束当前的执行路径,并抛出一个异常。异常可以被与之匹配的中间边界异常事件捕获。如果没有匹配的边界异常事件,默认会采用空终止事件对待。
要点:BPMN异常与Java异常是不一样的。事实上,两者没有任何共同点。BPMN异常事件是对业务异常建模的一种方式。Java异常则是以它所特有的方式来进行处理。
<endEvent id="myErrorEndEvent"> <errorEventDefinition errorRef="myError" /> </endEvent>
errorRef 属性可以引用流程之外定义的error元素。
<error id="myError" errorCode="123" /> ... <process id="myProcess"> ...
error元素的errorCode属性将用来查找与之匹配的捕获边界异常事件。如果errorRef与任何定义的异常都不匹配,那么errorRef会被当作errorCode的简写来使用。这是Activiti特有的简写。更具体地,在功能上下面的片段
<error id="myError" errorCode="error123" /> ... <process id="myProcess"> ... <endEvent id="myErrorEndEvent"> <errorEventDefinition errorRef="myError" /> </endEvent>
等价于
<endEvent id="myErrorEndEvent"> <errorEventDefinition errorRef="error123" /> </endEvent>
顺序流
顺序流是两个流程元素的连接者。一个元素在流程执行期间被访问后,流程会沿着该元素所有输出顺序流继续执行。这意味着BPMN 2.0默认行为是并行的:两个输出顺序流会创建两条独立、并行的执行路径。
顺序流要有流程唯一的id,以及指向现有起始元素和目标元素的引用。
<sequenceFlowid="flow1"sourceRef="theStart"targetRef="theTask"/>
条件顺序流
可以在顺序流上定义条件。当顺序流程左侧是BPMN 2.0的活动时,默认会计算其输出顺序流上的条件。选取条件成立的输出顺序流来执行。如果选取了多个顺序流,就会创建多个执行路径,并且流程会以并行的方式来执行。
注意:以上适用于BPMN 2.0的活动(以及事件),但是不适用于分支。根据分支的类型,其会以其特有的方式来处理带有条件的顺序流。
条件顺序流被形象化成始点为一个小菱形的普通顺序流。条件表达式紧挨着顺序流。
<sequenceFlow id="flow"sourceRef="theStart"targetRef="theTask"> <conditionExpressionxsi:type="tFormalExpression"> <![CDATA[${order.price > 100 && order.price < 250}]]> </conditionExpression> </sequenceFlow>
目前,conditionExpression只能使用UEL,关于此的详细信息见表达式一节。使用的表达式必须解析为布尔类型的值,否则在计算条件时会抛出异常。
下面的示例以典型的JavaBean风格通过getters来引用流程变量的数据。
<conditionExpressionxsi:type="tFormalExpression"> <![CDATA[${order.price > 100 && order.price < 250}]]> </conditionExpression>
该示例调用了一个返回布尔类型值的方法
<conditionExpression xsi:type="tFormalExpression"> <![CDATA[${order.isStandardOrder()}]]> </conditionExpression>
默认顺序流
所有BPMN 2.0任务以及分支都可以有一个默认顺序流。当且仅当没有其它顺序流被选择时,才会选择该顺序流作为活动的输出顺序流。默认顺序流上的条件总是被忽略掉。
默认顺序流被形象化成起点带‘斜线’的普通顺序流。
某个活动的默认顺序流是由那个活动上的default属性定义的。下面的XML片段展示了包含一个默认顺序流flow2的排他分支。只有当conditionA和conditionB都为false时,才会选取它作为分支的输出顺序流。
<exclusiveGatewayid="exclusiveGw"name="Exclusive Gateway"default="flow2"/> <sequenceFlowid="flow1"sourceRef="exclusiveGw"targetRef="task1"> <conditionExpressionxsi:type="tFormalExpression">${conditionA}</conditionExpression> </sequenceFlow> <sequenceFlowid="flow2"sourceRef="exclusiveGw"targetRef="task2"/> <sequenceFlowid="flow3"sourceRef="exclusiveGw"targetRef="task3"> <conditionExpressionxsi:type="tFormalExpression">${conditionB}</conditionExpression>
</sequenceFlow>
Gateways 分支
gateway用来控制执行流(或如BPMN 2.0描述的,执行令牌)。gateway可以回收或创建令牌。 gateway被形象化为里面有图标的菱形。图标说明了gateway的类型。