接着上篇继续介绍activiti的流程运行控制服务。
流程实例与执行流:
1、流程实例(ProcessInstance)表示一次工作流业务的数据实体;
2、执行流(Execution)表示流程实例汇总具体的执行路径;
3、流程实例接口(ProcessInstance)继承了执行流(Execution),流程实例在执行流的基础上扩展了一些其他系列的操作。
流程触发:
1、使用trigger触发ReceiveTask节点,当流程执行到这个Task节点的时候就会暂停下来,等待需要接受的事件去执行;
2、触发信号捕获事件signalEventReceived,当只有获取这个信号以后才能继续执行;
3、触发消息捕获事件messageEventReceived,只有捕获到某些消息后才能继续执行。
注:这里触发信号与触发消息非常相似,但是信号是可以全局发送信号,消息只能针对某个流程实例发送消息。
接下来我们来测试一下:
首先只是为了测试,所以我们使用一个简单的流程图:
然后用代码演示一下执行效果:
先要定义并且设计如上一样的流程图,创建my-process-trigger.bpmn20.xml流程文件:
my-process-trigger.bpmn20.xml文件中内容如下:
然后在上一篇创建的RuntimeServiceTest测试类中新增测试函数:
/**
* 流程触发trigger
*/
@Test
@org.activiti.engine.test.Deployment(resources = "my-process-trigger.bpmn20.xml")
public void testTrigger(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("my-process");//通过流程图中的来启动流程
Execution execution = runtimeService.createExecutionQuery()
.activityId("someTask").singleResult(); //获取执行流对象,someTask是其中事件的id
LOGGER.info("execution = [{}]" , execution);
runtimeService.trigger(execution.getId()); //获取这个的id来触发执行
execution = runtimeService.createExecutionQuery()
.activityId("someTask").singleResult(); //重新获取someTask
LOGGER.info("execution = [{}]" , execution); //重新打印
}
测试结果:
Loading XML bean definitions from class path resource [activiti.cfg.xml]
Activiti 5 compatibility handler implementation not found or error during instantiation : org.activiti.compatibility.DefaultActiviti5CompatibilityHandler. Activiti 5 backwards compatibility disabled.
performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
ProcessEngine default created
execution = [Execution[ id '5' ] - activity 'someTask - parent '4']
execution = [null]
可以看到我们第一次输出execution时可以获取到执行流对象 Execution[ id '5' ] - activity 'someTask - parent '4'。当触发信号发出去以后,流程执行过去则第二次输出execution时这个执行对象就已经没有了,也就是后面的null。
这里使用流程图如下:
创建my-process-signal-received.bpmn20.xml流程文件,其中xml流程文件内容:
在RuntimeServiceTest测试类中新增测试函数:
/**
* 测试流程触发的 signalEventReceived 信号捕获
*/
@Test
@org.activiti.engine.test.Deployment(resources = "my-process-signal-received.bpmn20.xml")
public void testSignalEventReceived(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("my-process");//通过流程图中的来启动流程
Execution execution = runtimeService.createExecutionQuery()
.signalEventSubscriptionName("my-signal").singleResult(); //获取执行流对象,my-signal是其中信号
LOGGER.info("execution = [{}]" , execution);
//来触发我们定义的信号,发出一个my-signal的信号,若不是这个信号则下面输出还停留在signal-received这一步
runtimeService.signalEventReceived("my-signal");
execution = runtimeService.createExecutionQuery()
.signalEventSubscriptionName("my-signal").singleResult();
LOGGER.info("execution = [{}]" , execution); //重新打印
}
输出结果:
Loading XML bean definitions from class path resource [activiti.cfg.xml]
Activiti 5 compatibility handler implementation not found or error during instantiation : org.activiti.compatibility.DefaultActiviti5CompatibilityHandler. Activiti 5 backwards compatibility disabled.
performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
ProcessEngine default created
execution = [Execution[ id '5' ] - activity 'signal-received - parent '4']
execution = [null]
信号与具体流程实例没有关系,但是这里的消息必须指定流程执行对象的ID才能继续执行。
测试流程图如下:
创建my-process-message-received.bpmn20.xml流程文件,xml流程文件内容:
在RuntimeServiceTest测试类中新增测试函数:
/**
* 测试事件触发的 messageEventReceived 信号捕获
*/
@Test
@org.activiti.engine.test.Deployment(resources = "my-process-message-received.bpmn20.xml")
public void testMessageEventReceived(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("my-process");//通过流程图中的来启动流程
Execution execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("my-message").singleResult(); //获取执行流对象,my-message是消息
LOGGER.info("execution = [{}]" , execution);
runtimeService.messageEventReceived("my-message",execution.getId()); //将流程执行ID作为参数传进去
execution = runtimeService.createExecutionQuery()
.messageEventSubscriptionName("my-message").singleResult();
LOGGER.info("execution = [{}]" , execution); //重新打印
}
输出结果:
Loading XML bean definitions from class path resource [activiti.cfg.xml]
Activiti 5 compatibility handler implementation not found or error during instantiation : org.activiti.compatibility.DefaultActiviti5CompatibilityHandler. Activiti 5 backwards compatibility disabled.
performing create on engine with resource org/activiti/db/create/activiti.h2.create.engine.sql
performing create on history with resource org/activiti/db/create/activiti.h2.create.history.sql
performing create on identity with resource org/activiti/db/create/activiti.h2.create.identity.sql
ProcessEngine default created
execution = [Execution[ id '5' ] - activity 'message-received - parent '4']
execution = [null]
创建my-process-message.bpmn20.xml流程文件,其中流程内容如下:
RuntimeServiceTest测试类中的测试函数:
/**
* 基于message启动流程
*/
@Test
@org.activiti.engine.test.Deployment(resources = "my-process-message.bpmn20.xml")
public void testMessageStart(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService
.startProcessInstanceByMessage("my-message"); //通过流程图中的 来启动流程
LOGGER.info("processInstance = [{}]", processInstance);
}
输出结果:
可以看到基于message也可以正常启动流程实例。
基于key启动与message启动的区别?
基于key启动更为简洁,基于message启动则有点繁琐,需要在流程定义文件里面定义一个message标签。并且得到的ProcessInstance[5],key则是ProcessInstance[4]。因为基于message启动会在数据库的表中插入一条记录,所以就变成了5。启动过程是根据message信号从事件订阅中找到订阅这个信号的id,最后找到流程定义的key然后启动。