Activiti6.0學習實踐(7)-核心api:RuntimeService流程運行控制服務

RuntimeService是流程引擎中的流程運行控制服務,主要提供了以下功能:

  1. 啓動流程及對流程數據的控制
  2. 流程實例(ProcessInstance)與執行流(Exceution)查詢
  3. 觸發流程操作、接收消息和信號

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);

}

執行日誌:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章