如下图所示,在提单页面,发起人需要手动选择走部门内分组审核还是部门负责人审核,对于这种由发起人选择走不同分支的且分支条件不是来自业务系统的情形,需要在流程模型上设置变量并赋初始化值,下面介绍如何设置及使用。
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0kg5kad" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.9.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.15.0">
<bpmn:process id="Process_Demo11" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="开始事件" camunda:initiator="starter">
<bpmn:outgoing>Flow_1w8hx7u</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_1w8hx7u" sourceRef="StartEvent_1" targetRef="Activity_1drnsx4" />
<bpmn:userTask id="Activity_06ntta4" name="起草" camunda:assignee="${starter}">
<bpmn:incoming>Flow_06hawzz</bpmn:incoming>
<bpmn:outgoing>Flow_1us3p2e</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1us3p2e" sourceRef="Activity_06ntta4" targetRef="Gateway_0a7spma" />
<bpmn:inclusiveGateway id="Gateway_0a7spma" name="发起人选择">
<bpmn:incoming>Flow_1us3p2e</bpmn:incoming>
<bpmn:outgoing>Flow_0dm15h8</bpmn:outgoing>
<bpmn:outgoing>Flow_1d5313z</bpmn:outgoing>
</bpmn:inclusiveGateway>
<bpmn:sequenceFlow id="Flow_0dm15h8" name="1" sourceRef="Gateway_0a7spma" targetRef="Activity_1h2epaw">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${para_var.indexOf("1") > -1}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:exclusiveGateway id="Gateway_1t7zl4t">
<bpmn:incoming>Flow_0ydcrpn</bpmn:incoming>
<bpmn:incoming>Flow_1d5313z</bpmn:incoming>
<bpmn:outgoing>Flow_1y299hk</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0ydcrpn" sourceRef="Activity_1h2epaw" targetRef="Gateway_1t7zl4t" />
<bpmn:sequenceFlow id="Flow_1d5313z" name="0" sourceRef="Gateway_0a7spma" targetRef="Gateway_1t7zl4t">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${para_var.indexOf("0") > -1}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:userTask id="Activity_1h2epaw" name="部门内分组审核">
<bpmn:incoming>Flow_0dm15h8</bpmn:incoming>
<bpmn:outgoing>Flow_0ydcrpn</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1y299hk" sourceRef="Gateway_1t7zl4t" targetRef="Activity_09moh95" />
<bpmn:userTask id="Activity_0ccrd9s" name="HR审批">
<bpmn:incoming>Flow_06cclke</bpmn:incoming>
<bpmn:outgoing>Flow_097rgey</bpmn:outgoing>
</bpmn:userTask>
<bpmn:endEvent id="Event_1jkyih3" name="结束事件">
<bpmn:incoming>Flow_097rgey</bpmn:incoming>
</bpmn:endEvent>
<bpmn:userTask id="Activity_09moh95" name="部门负责人审核">
<bpmn:incoming>Flow_1y299hk</bpmn:incoming>
<bpmn:outgoing>Flow_06cclke</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_06cclke" sourceRef="Activity_09moh95" targetRef="Activity_0ccrd9s" />
<bpmn:sequenceFlow id="Flow_097rgey" sourceRef="Activity_0ccrd9s" targetRef="Event_1jkyih3" />
<bpmn:sequenceFlow id="Flow_06hawzz" sourceRef="Activity_1drnsx4" targetRef="Activity_06ntta4" />
<bpmn:task id="Activity_1drnsx4" name="初始化">
<bpmn:extensionElements>
<camunda:inputOutput>
<camunda:outputParameter name="para_var">0,1</camunda:outputParameter>
</camunda:inputOutput>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1w8hx7u</bpmn:incoming>
<bpmn:outgoing>Flow_06hawzz</bpmn:outgoing>
</bpmn:task>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_Demo11">
<bpmndi:BPMNEdge id="Flow_1y299hk_di" bpmnElement="Flow_1y299hk">
<di:waypoint x="885" y="277" />
<di:waypoint x="970" y="277" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1d5313z_di" bpmnElement="Flow_1d5313z">
<di:waypoint x="655" y="277" />
<di:waypoint x="835" y="277" />
<bpmndi:BPMNLabel>
<dc:Bounds x="742" y="259" width="7" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ydcrpn_di" bpmnElement="Flow_0ydcrpn">
<di:waypoint x="790" y="148" />
<di:waypoint x="860" y="148" />
<di:waypoint x="860" y="252" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0dm15h8_di" bpmnElement="Flow_0dm15h8">
<di:waypoint x="630" y="252" />
<di:waypoint x="630" y="148" />
<di:waypoint x="690" y="148" />
<bpmndi:BPMNLabel>
<dc:Bounds x="642" y="197" width="7" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1us3p2e_di" bpmnElement="Flow_1us3p2e">
<di:waypoint x="530" y="277" />
<di:waypoint x="605" y="277" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1w8hx7u_di" bpmnElement="Flow_1w8hx7u">
<di:waypoint x="198" y="277" />
<di:waypoint x="260" y="277" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_06cclke_di" bpmnElement="Flow_06cclke">
<di:waypoint x="1070" y="277" />
<di:waypoint x="1180" y="277" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_097rgey_di" bpmnElement="Flow_097rgey">
<di:waypoint x="1280" y="277" />
<di:waypoint x="1372" y="277" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_06hawzz_di" bpmnElement="Flow_06hawzz">
<di:waypoint x="360" y="277" />
<di:waypoint x="430" y="277" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Gateway_0ap0c50_di" bpmnElement="Gateway_0a7spma">
<dc:Bounds x="605" y="252" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="605" y="309" width="55" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1t7zl4t_di" bpmnElement="Gateway_1t7zl4t" isMarkerVisible="true">
<dc:Bounds x="835" y="252" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_16za7az_di" bpmnElement="Activity_1h2epaw">
<dc:Bounds x="690" y="108" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0yynbrt_di" bpmnElement="Activity_09moh95">
<dc:Bounds x="970" y="237" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0rfuc5g_di" bpmnElement="Activity_0ccrd9s">
<dc:Bounds x="1180" y="237" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1370nng_di" bpmnElement="Event_1jkyih3">
<dc:Bounds x="1372" y="259" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1368" y="302" width="44" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="162" y="259" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="158" y="302" width="44" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0mhth21_di" bpmnElement="Activity_1drnsx4">
<dc:Bounds x="260" y="237" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1b73k2c_di" bpmnElement="Activity_06ntta4">
<dc:Bounds x="430" y="237" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
Camunda Modeler没有在流程属性上设置全局变量功能,我们这里借助一个Task初始化节点来实现,在初始化节点处设置输出变量para_var,默认值为“0,1”,在流程模型的变量信息处能看到所有输出变量信息。
注:只有输出变量的作用域是全局的,输入变量的作用域是只对当前节点的
包容网关分支条件设置,para_var包含1,则走部门内分组审核,包含0则走部门负责人审核。
创建流程并检查返回变量
@Test
public void createProcess() {
try {
String processDefKey = "Process_Demo11";
String userId = "bx1";
AuthenticationService authenticationService = new AuthenticationService();
// 获取当前流程引擎的名称
String engineName = processEngine.getName();
// 用户无密码登录
UserAuthentication authentication = (UserAuthentication) authenticationService
.createAuthenticate(engineName, userId, null, null);
//设置当前用户为操作人
identityService.setAuthenticatedUserId(authentication.getName());
// 创建流程
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefKey);
//流程创建成功获取变量信息
if (processInstance != null && StringUtils.isNotBlank(processInstance.getId())) {
Map<String, Object> vars = runtimeService.getVariables(processInstance.getId());
logger.info(JSON.toJSONString(vars));
} else {
throw new Exception("创建流程实例失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
查看打印日志,有该流程实例的流程全局变量返回
2021-09-03 21:50:45,885 [main] INFO org.camunda.bpm.DemoApplicationTest:682 - {"starter":"bx1","para_var":"0,1"}
在Cockpit里也能看到,流程发起后初始化节点自动执行了,并且为该流程实例设置了变量para_var
然后通过获取下一节点方法,获取到起草节点后的节点。
[
{
"assignment":"",
"name":"部门内分组审核",
"key":"Activity_1h2epaw"
},
{
"assignment":"",
"name":"部门负责人审核",
"key":"Activity_09moh95"
}
]
起草人在选定好对应的节点和节点处理人后提交到对应分支执行,下面示例将para_var=1来表示实现流转到“部门内分组审核”节点
思考:是否有其他方法实现呢?
@Test
public void submitTask3() {
try {
String userId = "bx1";
String taskId = "a20e9285-0cc4-11ec-b197-00ff0269ba71";
String processInstId = "a1f64f8b-0cc4-11ec-b197-00ff0269ba71";
String nextUserId = "bx2";
AuthenticationService authenticationService = new AuthenticationService();
String engineName = processEngine.getName();
UserAuthentication authentication = (UserAuthentication) authenticationService
.createAuthenticate(engineName, userId, null, null);
logger.info("authentication--------->" + authentication.getName());
identityService.setAuthenticatedUserId(authentication.getName());
List<TaskDto> taskList = new ArrayList<TaskDto>();
//目标节点的分支变量为1
runtimeService.setVariable(processInstId, "para_var", "1");
//完成任务
taskService.complete(taskId);
taskList = simpleGetTasks(processInstId);
System.out.println(JSON.toJSONString(taskList));
if (taskList != null && taskList.size() == 1) {
//设置目标节点处理人
taskService.setAssignee(taskList.get(0).getId(), nextUserId);
}
taskList = simpleGetTasks(processInstId);
System.out.println(JSON.toJSONString(taskList));
} catch (Exception e) {
e.printStackTrace();
}
}
提交后,流程流转到“部门内分组审核”,对应审批人为"bx2",流程变量para_var为“1”。
任务操作记录能看到是有bx1发给bx2的。
若将para_var修改为0,处理人为“bx3”,查看Cockpit里边,发现流程流转符合预期,流转到“部门负责人审核”节点,任务是由bx1发给bx3的。
@Test
public void submitTask3() {
try {
String userId = "bx1";
String taskId = "7b1fc48b-0cc6-11ec-bd79-00ff0269ba71";
String processInstId = "7afea7f1-0cc6-11ec-bd79-00ff0269ba71";
String nextUserId = "bx3";
AuthenticationService authenticationService = new AuthenticationService();
String engineName = processEngine.getName();
UserAuthentication authentication = (UserAuthentication) authenticationService
.createAuthenticate(engineName, userId, null, null);
logger.info("authentication--------->" + authentication.getName());
identityService.setAuthenticatedUserId(authentication.getName());
List<TaskDto> taskList = new ArrayList<TaskDto>();
//目标节点的分支变量为1
runtimeService.setVariable(processInstId, "para_var", "0");
//完成任务
taskService.complete(taskId);
taskList = simpleGetTasks(processInstId);
System.out.println(JSON.toJSONString(taskList));
if (taskList != null && taskList.size() == 1) {
//设置目标节点处理人
taskService.setAssignee(taskList.get(0).getId(), nextUserId);
}
taskList = simpleGetTasks(processInstId);
System.out.println(JSON.toJSONString(taskList));
} catch (Exception e) {
e.printStackTrace();
}
}