2023年11月29日发(作者:)

Activiti(四)--流程事件

1 事件分类

1.1 按照事件的位置分类

开始事件:表⽰流程开始的事件

结束事件:表⽰流程结束的事件

中间事件:出现在流程中,单独作为流程节点的事件

1.2 按照事件的特性分类

Catching事件:会⼀直等待被触发

Throwing事件:会⾃动触发并反馈结果

2.事件定义

2.1 定时器事件定义

定时器事件是由定时器触发的事件,定时器事件的定义可以嵌套在开始事件,中间事件或者边界事件中.配置如下:

<timerEventDefinition>

<timeDate>2018-10-10T06:00:00timeDate>

timerEventDefinition>

<timerEventDefinition>

<timeDuration>PT5StimeDuration>

timerEventDefinition>

<timerEventDefinition>

<timeCycle>R2/PT1MtimeCycle>

timerEventDefinition>

以上三个timerEventDefinition的⼦元素,在定义时间时,都需要遵守ISO 8601的国际标准,该标准是关于⽇期和时间的表⽰⽅法的标准,其中

timeCycle还⽀持使⽤cron表达式来设定定时器的重复间隔.

2.2 错误事件定义

错误事件会被定义的错误信息所触发,BPMN中的错误事件主要⽤于处理流程中出现的业务异常.流程中的业务异常与Java中的Exception是

不同的概念,在设计业务时,如果满⾜⼀定的条件,那么就会触发错误事件.

<error id="myError" errorCode="123">error>

<process id="testProcess" name="testProcess">

<endEvent id="myErrorEndEvent">

<errorEventDefinition errorRef="myError"/>

endEvent>

process>

BPMN规范规定⼀个error元素需要包含以下属性

id:该元素的唯⼀标识

name:元素的名称

errorCode:错误事件编码,当处理业务时抛出相应的异常代码,流程引擎会根据该错误代码⾃动匹配到该error元素,定义error元素必须设定

errorCode属性

structureRef:结构引⽤属性

2.3 信号事件定义

信号事件是⼀种引⽤了信号定义的事件,可以使⽤⼀个信号向全部的流程发送⼴播(前提是流程定义使⽤了同样名称的信号),信号事件的xml配

置如下:

<signal id="signalA" name="signalA">signal>

<process id="testProcess" name="testProcess">

...

<signalEventDefintion signalRef="signalA">signalEventDefinition>

...

process>

id:该元素的唯⼀标识,必须提供

name:signal元素的名称,必须提供,否则Activiti在解析流程⽂件时会抛出异常,在⼀个流程定义中,不允许同时出现多个name相同的signal元

素,否则将抛出异常

structureRef:该属性与错误事件的structureRef属性⼀样

2.4 消息事件定义

消息事件是⼀种引⽤了消息定义的事件,与信号不同的是,消息只能指向⼀个接收⼈,⽽不能像信号⼀样进⾏⼴播.使⽤messageRef属性引⽤⼀

个消息(引⽤消息元素的id);

<message id="myMsg" name="myMsg">message>

<process id="medProcess" name="medProcess">

...

<messageEventDefinition messageRef="myMsg">messageEventDefinition>

...

process>

id:该元素的唯⼀标识

name:消息的名称,使⽤RuntimeService的messageEventReceived⽅法时传⼊该参数

itemRef:⽤于指定该消息引⽤的itemDefinition元素

2.5 取消事件定义

取消事件使⽤在事务⼦流程(Transaction Sub-Process)模型中,取消事件定义可以使⽤在边界事件和结束事件中,称为取消边界事件和取消

结束时间

<cancelEventDefinition>cancelEventDefinition>

2.6 补偿事件定义

补偿机制主要⽤于对已经成功完成的流程做回退处理,因为这些流程的结果吗有可能不是我们所期望的,如果当前流程活动时激活状态的,那么

不能使⽤补偿机制,但是可以考虑取消机制,相反,取消友可能会导致补偿的触发.

<compensateEventDefinition><compensateEventDefinition/>

3 开始事件

3.1 ⽆指定开始事件

没有为其指定任务触发条件的开始事件为⽆指定开始事件,使⽤⽆指定开始事件,流程引擎并不知道流程将会在什么时候开始,如果需要启动流

程,就必须使⽤RuntimeService的startProcessByXXX⽅法.

<process id="timerStartProcess" name="timerStartProcess">

<startEvent id="startEvent1" name="start">startEvent>

<userTask id="userTask1" name="task">userTask>

<endEvent id="endEvent1" name="End">endEvent>

<sequenceFlow id="flow1" name="" sourceRef="startEvent1" targetRef="userTask1">sequenceFlow>

<sequenceFlow id="flow2" name="" sourceRef="userTask1" targetRef="endEvent1">sequenceFlow>

process>

3.2 定时器开始事件

在开始事件中加⼊定时器事件定义,该开始事件就成为⼀个定时器开始事件,当时符合条件,流程启动,⽽并不需要像⽆指定开始事件⼀样,使⽤

API启动流程

<process id="timerStartProcess" name="timerStartProcess">

<startEvent id="timerstartevent1" name="Timer start">

<timerEventDefinition>

<timeCycle>0/5 * * * * ?timeCycle>

timerEventDefinition>

startEvent>

<userTask id="userTask1" name="check log">userTask>

<endEvent id="endEvent1" name="end">endEvent>

<sequenceFlow id="flow1" name="" sourceRef="timerstartevent1" targetRef="userTask1">sequence>

<sequenceFlow id="flow2" name="" sorrceRef="usertask1" targetRef="endevent1">sequenceFlow>

process>

3.3 消息开始事件

为开始事件加⼊消息事件的定义可以使其成为消息开始事件,此时可以使⽤RuntimeService的startProcessByMessage⽅法启动流程

<message id="msgA">message>

<process id="myProcess" name="myProcess">

<userTask id="userTask1" name="myTask">userTask>

<endTask id="endevent1" name="End">endEvent>

<startEvent id="messagestartevent1" name="Message start">

<messageEventDefintion messageRef="msgA">messageEventDefinition>

startEvent>

<sequenceFlow id="flow1" name="" sourceRef="messagestartevent1" targetRef="userTask1">sequenceFlow>

<sequenceFlow id="flow2" name="" sourceRef="userTask1" targetRef="endevent1">sequenceFlow>

process>

//

部署流程⽂件

repositoryService.createDeployment().addClasspathResource("bpmn/").deploy();

//

启动流程

runtimeService.startProcessInstanceByMessage("msgA");

//

查询流程

runtimeService.createProcessInstanceQuery().count();

3.4 错误开始事件

错误开始事件只能在事件⼦流程中使⽤,该事件不能在其他的流程中使⽤,包括最⾼级流程(Top-Level Process),嵌套⼦流程(Sub-Process)

和调⽤⼦流程(Call Activity).

假设当前有⼀个检查服务器8080端⼝的流程,当流程启动后,会检查服务器的8080端⼝是否存在,如果不存在,则执⾏事件⼦流程,对应的流程

图和代码如下:

<error id="" errorCode="error">error>

<Process id="errorStartProcess" name="errorStartProcess">

<startEvent id="startEvent1" name="Start">startEvent>

<subProcess id="eventProcess1" name="Event sub Process" triggeredByEvent="true">

<startEvent id="errorstartevent1" name="Error start">

<errorEventDefintion errorRef="connectError">errorEventDefinition>

startEvent>

<serviceTask id="userTask1" name="Sub Task" activiti:class="ErrorDelegate">serviceTask>

<endEvent id="endevent1" name="End">endEvent>

<sequenceFlow id="flow2" name="" sourceRef="errorstartevent1" targetRef="usertask1">sequenceFlow>

<sequenceFlow id="flow3" name="" sourceRef="usertask1" targetRef="endevent1">sequenceFLow>

subprocess>

<serviceTask id="servicetask1" name="Service Task" activiti:class="erverDelegate">serviceTask>

<endEvent id="endevent2" name="End">endEvent>

<sequenceFlow id="flow4" name="" sourceRef="startevent1" targetRef="serviceTask1">sequenceFlow>

<sequenceFlow id="flow5" name="" sourceRef="servicetask1" targetRef="endevent2">sequenceFlow>

process>

try{

System.out.println("开始检查8080端⼝");

//8080

连接本机的端⼝

Socket socket = new Socket("127.0.0.1",8080);

System.out.println("检查8080端⼝完成");

}catch(Exception e){

System.out.println("检查时出现异常, 抛出错误");

//,BpmError,error code"error"

连接出现异常则抛出

throw new org.activiti.engine.delegate.BpmnError("error");

}

4 结束事件

4.1 ⽆指定结束事件

与⽆指定开始事件⼀样,⽆指定结束事件是指流程在结束时,不会进⾏任务的额外操作,结束事件中不使⽤任何事件的定义.

<process id="myProcess" name="myProcess">

<startEvent id="startEvent1" name="Start">startEvent>

<userTask id="userTask1" name="User Task">userTask>

<endEvent id="endEvent1" name="End">endEvent>

<sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="usertask1">sequenceFLow>

<sequenceFlow id="flow2" name="" sourceRef="userTask1" targetRef="endevent1">sequenceFlow>

process>

4.2 错误结束事件

当执⾏流到达错误结束事件时,会结束该执⾏流并且抛出错误,该错误可以被"错误边界事件"捕获,如果没有定义任何的错误边界事件,那么其将

//

部署流程⽂件

repositoryService.createDeployment().addClasspathResource("bpmn/").deploy();

//

启动流程

runtimeService.startProcessInstanceByKey("errorEndProcess");

//,

结束⼦流程中的任务并设置结束任务

Task subTask = taskService.createTaskQuery().singleResult();

Map<String,Object> vars = new HashMap<String,Object>();

//successtrue

设置参数为

vars.put("success","true");

taskService.complete(sybTask.getId(),vars);

//

查看到达的任务

List<Task> tasks = taskService.createTaskQuery().list();

for(Task task : tasks){

System.out.println(task.getName());

}

4.3 取消结束事件和取消边界事件

取消结束事件只能在事务⼦流程中使⽤,该事件表⽰事务将会取消,并且会触发依附在事务⼦流程上的取消边界事件,与错误结束事件类似,取消

结束事件会被抛出,⽽取消边界事件则会捕获该事件.事务⼦流程的取消事件的触发,还会导致补偿的触发.

//

部署流程⽂件

repositoryService.createDeployment().addClasspathResource("bpmn/").deploy();

//

启动流程

runtimeService.startProcessInstanceByKey("cancleProcess");

//

初始化流程参数

Map<String,Object> vars = new HashMap<String,Object>();

vars.put("confirm",false);

// ,task

设置参数完成⽤户确认的

Task task = taskService.createTaskQuery().singleResult();

taskService.complete(task.getId(),vars);

4.4 中⽌结束事件

当流程执⾏到终⽌结束事件时,当前的流程将会被终结,该事件可以在嵌⼊⼦流程,调⽤⼦流程,事件⼦流程或者事务⼦流程中使⽤…终⽌结束事

件使⽤terminateEventDefinition元素作为事件定义.如果将元素的activiti:terminateAll属性设置为true,bane当终⽌结束事件被触发时,流

程实例的全部执⾏流均会被终结.

...//

部署流程

ProcessInstance pi = runtimeService.startProcessInstanceByKey("terminateAll");

//

查询执⾏流数量

long exeCount = runtimeService.createExecutionQuery().processInstanceId(pi1.getId()).count();

5 边界事件

BPMN2.0中定义了以下边界事件:消息(Message)边界事件,定时器边界事件,升级边界事件,错误边界事件,取消边界事件,补偿边界事件,条件

边界事件,信号边界事件,组合边界事件和并⾏组合边界事件

6 中间事件

中间事件按照其特性可以分为两类:中间catching事件和Throwing事件,当流程到达中间Catching事件时,它会⼀直等待,直到接收信息,还会