RuntimeService是流程引擎中的流程运行控制服务,主要提供了以下功能:
RuntimeService启动流程的常用方式(id,key,message),可选参数(businessKey,variables,tenantid),可以对变量进行设置和获取(是流程实例级别的,还是流程实例级别),下面通过一个测试代码来了解RuntimeService的各种接口
public class RuntimeServiceTest {
private static final Logger logger = LoggerFactory.getLogger(RuntimeServiceTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
public void test() {
}
流程的启动有三种方式,分别是通过key,id,builder的方式进行启动
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testStartByKey() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//设置一下流程的key
Map variables = Maps.newHashMap();
variables.put("key1","value1");
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变)
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process", variables);
logger.info("processInstance = {}, key={}", processInstance, processInstance.getProcessDefinitionKey());
}
执行日志如下:
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testStartById() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//通过流程定义对象获取流程id,这里会涉及使用流程的存储服务repositoryservice
ProcessDefinition processDefinition
= activitiRule.getRepositoryService().createProcessDefinitionQuery().singleResult();
//设置一下流程的key
Map variables = Maps.newHashMap();
variables.put("key1","value1");
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变)
ProcessInstance processInstance
= runtimeService.startProcessInstanceById(processDefinition.getId(), variables);
logger.info("processInstance = {}, key={}, id={}" , processInstance, processInstance.getProcessDefinitionKey(), processInstance.getId());
}
执行日志:
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testProcessInstanceBuilder() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//设置一下流程的key
Map variables = Maps.newHashMap();
variables.put("key1","value1");
//通过流程实例构建者进行流程启动
ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
ProcessInstance processInstance = processInstanceBuilder.businessKey("businesskey0001")
.processDefinitionKey("my-process")
.variables(variables)
.start();
logger.info("processInstance = {}, key={}", processInstance, processInstance.getProcessDefinitionKey());
}
执行日志如下:
可以看到以上几种方式启动是没有什么差别的。
可以通过设置变量的方式,使得流程可以携带数据(变量)进行流转。在流转的过程中,可以对流程变量进行修改和新增
//这段测试代码,对流程变量进行测试,包含变量的设置,新增,修改
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testVariables() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//设置一下流程的key
Map variables = Maps.newHashMap();
variables.put("key1","value1");
variables.put("key2","value2");
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变)
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process", variables);
logger.info("processInstance = {}, key={}", processInstance, processInstance.getProcessDefinitionKey());
//修改变量内容
runtimeService.setVariable(processInstance.getId(), "key3","value3"); //新增key
runtimeService.setVariable(processInstance.getId(), "key2","value2-2"); //修改key值
//获取变量
Map variables1 = runtimeService.getVariables(processInstance.getId());
logger.info("varialbles1 = {}", variables1);
}
执行日志:
首先要说明一下流程执行流和流程实例的关系:流程执行流表示流程实例中具体的执行路径,流程实例是一次工作流业务的数据实体。可以从流程实例的类定义可以看到,流程实例是继承于流程执行流的。
下面是流程执行流的一个例子:
//流程实例的查询
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testProcessInstanceQuery() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//设置一下流程的key
Map variables = Maps.newHashMap();
variables.put("key1","value1");
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变),启动后如果不停止,流程没有结束,处于等待状态
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process", variables);
logger.info("processInstance = {}, key={}", processInstance, processInstance.getProcessDefinitionKey());
//通过流程运行时服务获取执行对象
List executions = runtimeService.createExecutionQuery()
.listPage(0, 100);
for (Execution execution : executions) {
logger.info("execution ={}", execution);
}
}
执行结果如下:
流程执行过程中,可以通过trigger来触发流程接收事件或者消息进行流程的执行。我们通过下面的例子来演示:
首先创建一个新的bpmn文件,这个文件中将usertask替换为receiveTask,这个任务会进行触发消息或者事件的捕捉
然后我们在测试代码中这样进行触发;
//通过trigger来控制流程的执行
@Test
@Deployment(resources = {"my-process-trigger.bpmn20.xml"})
public void testTrigger() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变)
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process");
//创建执行流对象
Execution execution = runtimeService.createExecutionQuery().activityId("someTask")
.singleResult();
logger.info("execution = {}", execution);
runtimeService.trigger(execution.getId());
execution = runtimeService.createExecutionQuery().activityId("someTask")
.singleResult();
logger.info("execution = {}", execution);
}
执行结果:
从日志看,第一次打印出执行流的信息,然后trigger触发后,流程继续执行结束,这个时候执行流结束了,所以第二次打印的是null
流程执行也可以通过信号事件触发,下面例子就是一个通过信号事件触发的demo
首先也是需要构造一下流程定义文件,注意其中signalEventDefinition的属性定义
测试代码如下:
//通过信号来触发流程的执行
@Test
@Deployment(resources = {"my-process-signal.bpmn20.xml"})
public void testSignalEventReceived() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变)
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process");
//查找一下是否有等待触发的信号
Execution execution = runtimeService.createExecutionQuery().signalEventSubscriptionName("my-signal")
.singleResult();
logger.info("execution = {}", execution);
runtimeService.signalEventReceived ("my-signal");
execution = runtimeService.createExecutionQuery().signalEventSubscriptionName("my-signal")
.singleResult();
logger.info("execution = {}", execution);
}
流程启动后等待信号触发,在发出信号后,流程执行流执行完成。
下面学习一下如何通过消息进行触发
首先建立一个配置文件,配置用消息进行触发
注意图中的标红框处内容,具体测试函数如下:
//通过消息来触发流程的执行
@Test
@Deployment(resources = {"my-process-message.bpmn20.xml"})
public void testMessageReceived() {
//获取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//通过key方式启动流程实例。(流程多次启动id不同,但是key 不会变)
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process");
//查找一下是否有等待触发的信号
Execution execution = runtimeService.createExecutionQuery().messageEventSubscriptionName ("my-message")
.singleResult();
logger.info("execution = {}", execution);
runtimeService.messageEventReceived ("my-message",execution.getId());
execution = runtimeService.createExecutionQuery().messageEventSubscriptionName("my-message")
.singleResult();
logger.info("execution = {}", execution);
}
执行日志: