RuntimeService是流程引擎中的流程運行控制服務,主要提供了以下功能:
- 啓動流程及對流程數據的控制
- 流程實例(ProcessInstance)與執行流(Exceution)查詢
- 觸發流程操作、接收消息和信號
RuntimeService啓動流程的常用方式(id,key,message),可選參數(businessKey,variables,tenantid),可以對變量進行設置和獲取(是流程實例級別的,還是流程實例級別),下面通過一個測試代碼來了解RuntimeService的各種接口
1、創建一個測試類RuntimeServiceTest
public class RuntimeServiceTest {
private static final Logger logger = LoggerFactory.getLogger(RuntimeServiceTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
public void test() {
}
2、流程啓動
流程的啓動有三種方式,分別是通過key,id,builder的方式進行啓動
2.1 首先是通過key的方式ey的方式
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testStartByKey() {
//獲取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//設置一下流程的key
Map<String, Object> variables = Maps.newHashMap();
variables.put("key1","value1");
//通過key方式啓動流程實例。(流程多次啓動id不同,但是key 不會變)
ProcessInstance processInstance
= runtimeService.startProcessInstanceByKey("my-process", variables);
logger.info("processInstance = {}, key={}", processInstance, processInstance.getProcessDefinitionKey());
}
執行日誌如下:
2.2 通過id的方式
@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<String, Object> 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());
}
執行日誌:
2.3 通過構建者builder啓動
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testProcessInstanceBuilder() {
//獲取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//設置一下流程的key
Map<String, Object> 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());
}
執行日誌如下:
可以看到以上幾種方式啓動是沒有什麼差別的。
3、流程變量
可以通過設置變量的方式,使得流程可以攜帶數據(變量)進行流轉。在流轉的過程中,可以對流程變量進行修改和新增
//這段測試代碼,對流程變量進行測試,包含變量的設置,新增,修改
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testVariables() {
//獲取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//設置一下流程的key
Map<String, Object> 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<String, Object> variables1 = runtimeService.getVariables(processInstance.getId());
logger.info("varialbles1 = {}", variables1);
}
執行日誌:
4、流程執行流(execution)
首先要說明一下流程執行流和流程實例的關係:流程執行流表示流程實例中具體的執行路徑,流程實例是一次工作流業務的數據實體。可以從流程實例的類定義可以看到,流程實例是繼承於流程執行流的。
下面是流程執行流的一個例子:
//流程實例的查詢
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void testProcessInstanceQuery() {
//獲取runtimeService
RuntimeService runtimeService = activitiRule.getRuntimeService();
//設置一下流程的key
Map<String, Object> 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<Execution> executions = runtimeService.createExecutionQuery()
.listPage(0, 100);
for (Execution execution : executions) {
logger.info("execution ={}", execution);
}
}
執行結果如下:
5、流程觸發trigger
流程執行過程中,可以通過trigger來觸發流程接收事件或者消息進行流程的執行。我們通過下面的例子來演示:
首先創建一個新的bpmn文件,這個文件中將usertask替換爲receiveTask,這個任務會進行觸發消息或者事件的捕捉
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="my-process">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<!-- <userTask id="someTask" name="Activiti is awesome!" />-->
<receiveTask id="someTask" name="Activiti is awesome!" />
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
</definitions>
然後我們在測試代碼中這樣進行觸發;
//通過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
6、通過信號事件觸發
流程執行也可以通過信號事件觸發,下面例子就是一個通過信號事件觸發的demo
首先也是需要構造一下流程定義文件,注意其中signalEventDefinition的屬性定義
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<signal id="signalStart" name="my-signal"></signal>
<process id="my-process">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="signal-received" />
<intermediateCatchEvent id="signal-received">
<signalEventDefinition signalRef="signalStart"> </signalEventDefinition>
</intermediateCatchEvent>
<sequenceFlow id="flow2" sourceRef="signal-received" targetRef="end" />
<endEvent id="end" />
</process>
</definitions>
測試代碼如下:
//通過信號來觸發流程的執行
@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);
}
流程啓動後等待信號觸發,在發出信號後,流程執行流執行完成。
7、通過消息觸發
下面學習一下如何通過消息進行觸發
首先建立一個配置文件,配置用消息進行觸發
注意圖中的標紅框處內容,具體測試函數如下:
//通過消息來觸發流程的執行
@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);
}
執行日誌: