BPMN中的事件分类方式包括以下三种:
(1). 位置分类:开始事件、中间事件 | 边界事件、结束事件。
(2). 特性分类:捕获事件(Catching)、抛出事件(Throwing)。
(3). 事件定义分类:定时事件、错误事件、信号事件、消息事件。
- 定时事件
* 指定事件(timeDate)
* 指定持续时间(timeDuration)
* 周期执行(timeCycle)
<timerEventDefinition>
<timeDate>2020-04-27T10:10:10</timeDate>
</timerEventDefinition>
(1)定时开始事件
<startEvent id="start" >
<timerEventDefinition>
<timeDate>2020-04-27T10:10:10</timeDate>
</timerEventDefinition>
</startEvent>
(2)定时边界事件
<userTask id="someTask"/>
<boundaryEvent attachedToRef="somtTask" id="timeOutEvent"
cancelActivity="true">
<timerEventDefinition>
<timeDate>2020-04-27T10:10:10</timeDate>
</timerEventDefinition>
</boundaryEvent>
定时边界事件实战:
(1)首先修改配置文件,启动异步执行开关和执行日志。
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="asyncExecutorActivate" value="true"></property>
<property name="enableVerboseExecutionTreeLogging" value="true"></property>
</bean>
(2)编写流程定义文件。
<process id="my-process">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="userTask"/>
<!--定义阻塞的用户任务-->
<userTask id="userTask" name="阻塞task"/>
<sequenceFlow id="flow2" sourceRef="userTask" targetRef="end" />
<!--如果5秒内没有执行,将会触发边界事件-->
<boundaryEvent attachedToRef="userTask" id="timeEvent" cancelActivity="true">
<timerEventDefinition>
<timeDuration>PT5S</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<!--如果5秒内没有执行,将会跳转到 timeOutTask-->
<sequenceFlow sourceRef="timeEvent" targetRef="timeOutNode"></sequenceFlow>
<sequenceFlow sourceRef="timeOutNode" targetRef="end"></sequenceFlow>
<userTask id="timeOutNode" name="超时task"></userTask>
<endEvent id="end" />
</process>
(3)编写测试类进行测试:
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
@Deployment(resources = "my-process.bpmn20.xml")
public void test() throws InterruptedException {
ProcessInstance processInstance = activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
Task task = activitiRule.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
logger.info("当前的任务节点为 = {}", task.getName());
Thread.sleep(1000 * 10);
task = activitiRule.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
logger.info("当前的任务节点为 = {}", task.getName());
}
-
错误事件
错误事件用来处理业务流程中出现的异常。
<endEvent id="errorEvent" name="End">
<errorEventDefinition errorRef="customError"></errorEventDefinition>
</endEvent>
(1)错误边界事件
在流程定义文件的子流程中,可以判断附件是否满足要求,比如是否有用户能够处理此次流程,如果不满足则跳转到一个错误事件节点,错误边界事件会捕获到该事件,然后将流程跳转到处理错误的用户任务中。
//1. 当附加信息不够时,流程跳转到噶节点。
<endEvent id="errorEvent" name="End">
<errorEventDefinition errorRef="notEnoughInfo"></errorEventDefinition>
</endEvent>
//2. 进行捕获,通过sequenceFlow节点跳转到处理错误的用户任务中
<boundaryEvent attachedToRef="子流程id" cancelActivity="true">
<errorEventDefinition errorRef="errorEvent"></errorEventDefinition>
</boundaryEvent>
-
信号事件
(1)信号开始事件
编写流程定义文件
<signal id="mySignal" name="signal_start"></signal>
<process id="my-process">
<startEvent id="start">
<signalEventDefinition signalRef="mySignal"></signalEventDefinition>
</startEvent>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask"/>
<userTask id="someTask" name="用户任务节点"/>
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类发出信号,启动流程,最终程序会阻塞到 someTask节点上。
@Test
@Deployment(resources = "my-process.bpmn20.xml")
public void test() throws InterruptedException {
RuntimeService runtimeService = activitiRule.getRuntimeService();
runtimeService.signalEventReceived("signal_start");
Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
logger.info("当前的节点 task = {}", task.getName());
}
(2)信号中间事件
消息中间事件的流程定义节点中会包括两种节点,事件抛出节点和事件捕获节点。
<signal id="mySignal" name="signal_start"></signal>
<process id="my-process">
<intermediateThrowEvent name="throwEvent">
<signalEventDefinition signalRef="mySignal"></signalEventDefinition>
</intermediateThrowEvent>
<intermediateCatchEvent>
<signalEventDefinition signalRef="mySignal"></signalEventDefinition>
</intermediateCatchEvent>
</process>
- 消息事件
消息事件和信号事件类似,代码就不在演示了。
<message id="pay" name="pay_message"></message>
<message id="generateOrder" name="gene_message"></message>
<process id="my-process">
<startEvent id="start">
<messageEventDefinition messageRef="pay"></messageEventDefinition>
</startEvent>
<intermediateCatchEvent id="order">
<messageEventDefinition messageRef="generateOrder"></messageEventDefinition>
</intermediateCatchEvent>
</process>