1. 子流程
版权声明:本文部分为CSDN博主「司马缸砸缸了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接
1.1 简介
子流程是一种特殊的流程,它包含在大流程中的一部分。
分为嵌入式子流程,调用式子流程,事件子流程,事务子流程,特别子流程(Activiti6新添加的)。
2. 调用式子流程
2.1 简介
当流程执行到调用节点,会创建一个新分支,它是到达调用节点的流程的分支。 这个分支会用来执行子流程,默认创建并行子流程,就像一个普通的流程。 上级流程会等待子流程完成,然后才会继续向下执行。
适用于多个流程共用一个子流程的情况。
主流程和子流程间的参数传递通过In parameters和Out parameters来实现。
2.2 流程设计
说明:
- Called element :子流程key
- In parameters: 入参
- Out parameters: 出参
流程文件bpmn
子流程
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596096081889" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="subprocess2" isClosed="false" isExecutable="true" name="Subprocess2" processType="None">
<startEvent id="_2" name="开始"/>
<userTask activiti:assignee="user3" activiti:exclusive="true" id="_3" name="班长审批"/>
<endEvent id="_4" name="结束"/>
<sequenceFlow id="_5" sourceRef="_2" targetRef="_3"/>
<sequenceFlow id="_6" sourceRef="_3" targetRef="_4"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="subprocess2">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="110.0" y="235.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<omgdc:Bounds height="55.0" width="85.0" x="415.0" y="225.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4">
<omgdc:Bounds height="32.0" width="32.0" x="805.0" y="235.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_5" id="BPMNEdge__5" sourceElement="_2" targetElement="_3">
<omgdi:waypoint x="142.0" y="251.0"/>
<omgdi:waypoint x="415.0" y="252.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_3" targetElement="_4">
<omgdi:waypoint x="500.0" y="252.5"/>
<omgdi:waypoint x="805.0" y="251.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
主流程
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 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" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596100438814" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="s" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="开始"/>
<userTask activiti:assignee="user1" activiti:exclusive="true" id="_3" name="新建请假单"/>
<callActivity activiti:exclusive="true" calledElement="subprocess2" id="_4" name="调用子流程">
<extensionElements>
<activiti:in source="days" target="subDays"/>
<activiti:out source="subDays" target="mainDays"/>
</extensionElements>
</callActivity>
<userTask activiti:assignee="user2" activiti:exclusive="true" id="_5" name="完成"/>
<endEvent id="_6" name="结束"/>
<sequenceFlow id="_7" sourceRef="_2" targetRef="_3"/>
<sequenceFlow id="_8" sourceRef="_3" targetRef="_4"/>
<sequenceFlow id="_9" sourceRef="_4" targetRef="_5"/>
<sequenceFlow id="_10" sourceRef="_5" targetRef="_6"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="s">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="10.0" y="235.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<omgdc:Bounds height="55.0" width="85.0" x="225.0" y="235.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4" isExpanded="false">
<omgdc:Bounds height="55.0" width="85.0" x="530.0" y="240.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<omgdc:Bounds height="55.0" width="85.0" x="795.0" y="260.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
<omgdc:Bounds height="32.0" width="32.0" x="1000.0" y="265.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_3">
<omgdi:waypoint x="42.0" y="251.0"/>
<omgdi:waypoint x="225.0" y="262.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_4">
<omgdi:waypoint x="310.0" y="262.5"/>
<omgdi:waypoint x="530.0" y="267.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_4" targetElement="_5">
<omgdi:waypoint x="615.0" y="267.5"/>
<omgdi:waypoint x="795.0" y="287.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_5" targetElement="_6">
<omgdi:waypoint x="880.0" y="287.5"/>
<omgdi:waypoint x="1000.0" y="281.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
2.3 测试类
package com.yb.activiti6;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @version 1.0
* @date 2020/7/23
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiDemoTest20 {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private IdentityService identityService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ProcessEngine processEngine;
@Autowired
private HistoryService historyService;
/**
* 发布流程,测试调用式子流程
* @throws IOException
*/
@Test
public void deploymentProcesses_zip(){
Deployment deploy = repositoryService.createDeployment()
.name("测试-调用式子流程-1")//创建流程名称
.addClasspathResource("processes/activiti_s.bpmn")//主流程
.addClasspathResource("processes/activiti_s.png")//主流程
.addClasspathResource("processes/activiti_Subprocess2.bpmn")//子流程
.addClasspathResource("processes/activiti_Subprocess2.png")//子流程
.deploy();
System.out.println("部署id:"+deploy.getId());
System.out.println("部署名称:"+deploy.getName());
}
/**
* 启动流程,测试调用式子流程
*/
@Test
public void startProcess() {
//可根据id,key,message启动流程
ProcessInstance pi = runtimeService.startProcessInstanceByKey("s");
System.out.println("流程实例id:" + pi.getId());
System.out.println("流程定义id:" + pi.getProcessDefinitionId());
System.out.println("=========================================================");
//查询任务
List<Task> taskList = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("user1") // 指定某个人
.list();
for (Task task : taskList) {
System.out.println("--------------------------------------------");
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
// 参数
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("days", 10);
// 完成任务
taskService.complete(task.getId(), vars);
}
// 主流程中查询参数
Integer days = (Integer) runtimeService.getVariable(pi.getId(), "days");
System.out.println("主流程中参数days:" + days);
// 调用式子流程中查询参数
ProcessInstance subPi = runtimeService.createProcessInstanceQuery()
.processDefinitionKey("subprocess2")
.singleResult();
Integer subDays = (Integer) runtimeService.getVariable(subPi.getId(), "subDays");
System.out.println("子流程中参数subDays:" + subDays);
// 设置子流程参数
runtimeService.setVariable(subPi.getId(), "subDays", subDays -1);
try {
Thread.sleep(1000 * 3);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 查询任务
taskList = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("user3") // 指定某个人
.list();
for (Task task : taskList) {
System.out.println("--------------------------------------------");
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
// 完成任务
taskService.complete(task.getId());
}
//查询任务
taskList = taskService.createTaskQuery() // 创建任务查询
.taskAssignee("user2") // 指定某个人
.list();
for (Task task : taskList) {
System.out.println("--------------------------------------------");
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
}
System.out.println("--------------------------------------------");
// 主流程中查询参数
Integer mainDays = (Integer) runtimeService.getVariable(pi.getId(), "mainDays");
System.out.println("主流程中参数mainDays:" + mainDays);
}
}
2.4 运行
运行deploymentProcesses_zip()
2.4.1 启动流程
运行startProcess()
效果
总结:
在测试过程中遇到一个错:
org.activiti.engine.ActivitiObjectNotFoundException: no processes deployed with key ‘null’
原因是:Called element 属性没有设置。
到此调用式子流程测试学习结束。