此文章(系列),记录项目引入Camunda的过程与问题记录,不包含对于Camunda的介绍。
目前此文章写于Camunda还未正式启用时,只是熟悉一下,后续项目正式引用Camunda后会继续更新文章,所以在文末会记录一些待解决的问题,正式引入后思考解决方案。
流程图示例:
其中包含了两个人工审批节点,一个叫提交测试,一个叫审核测试;包含了一个自动节点,叫java测试;网关是配置的approve这个参数控制走向的,下面附上流程图文件。
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0ght17g" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.12.0">
<bpmn:process id="test" name="测试流程" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_0y59rpv</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:userTask id="test1" name="提交测试" camunda:candidateGroups="cjlgroup">
<bpmn:incoming>SequenceFlow_0y59rpv</bpmn:incoming>
<bpmn:outgoing>Flow_09n832u</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="SequenceFlow_0y59rpv" sourceRef="StartEvent_1" targetRef="test1" />
<bpmn:serviceTask id="test2" name="java测试" camunda:class="com.powershare.emsp.flow.service.delegate.Test">
<bpmn:incoming>Flow_1j3al1t</bpmn:incoming>
<bpmn:outgoing>Flow_0rg2b62</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="Event_0tirpzn">
<bpmn:incoming>Flow_0rg2b62</bpmn:incoming>
<bpmn:incoming>Flow_1fu356n</bpmn:incoming>
</bpmn:endEvent>
<bpmn:exclusiveGateway id="Gateway_1eh4b64">
<bpmn:incoming>Flow_09n832u</bpmn:incoming>
<bpmn:outgoing>Flow_1deqcsi</bpmn:outgoing>
<bpmn:outgoing>Flow_1j3al1t</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_09n832u" sourceRef="test1" targetRef="Gateway_1eh4b64" />
<bpmn:sequenceFlow id="Flow_1deqcsi" sourceRef="Gateway_1eh4b64" targetRef="test3">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approve==1}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_1j3al1t" sourceRef="Gateway_1eh4b64" targetRef="test2">
<bpmn:extensionElements>
<camunda:properties>
<camunda:property />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approve==2}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_0rg2b62" sourceRef="test2" targetRef="Event_0tirpzn" />
<bpmn:sequenceFlow id="Flow_1fu356n" sourceRef="test3" targetRef="Event_0tirpzn" />
<bpmn:userTask id="test3" name="审批测试">
<bpmn:incoming>Flow_1deqcsi</bpmn:incoming>
<bpmn:outgoing>Flow_1fu356n</bpmn:outgoing>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="test">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="229" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_14eoyii_di" bpmnElement="test1">
<dc:Bounds x="310" y="207" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1eh4b64_di" bpmnElement="Gateway_1eh4b64" isMarkerVisible="true">
<dc:Bounds x="505" y="222" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0zr2m8v_di" bpmnElement="test3">
<dc:Bounds x="750" y="360" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1elmo82_di" bpmnElement="test2">
<dc:Bounds x="750" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0tirpzn_di" bpmnElement="Event_0tirpzn">
<dc:Bounds x="1042" y="229" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="SequenceFlow_0y59rpv_di" bpmnElement="SequenceFlow_0y59rpv">
<di:waypoint x="215" y="247" />
<di:waypoint x="310" y="247" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_09n832u_di" bpmnElement="Flow_09n832u">
<di:waypoint x="410" y="247" />
<di:waypoint x="505" y="247" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1deqcsi_di" bpmnElement="Flow_1deqcsi">
<di:waypoint x="530" y="272" />
<di:waypoint x="530" y="400" />
<di:waypoint x="750" y="400" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1j3al1t_di" bpmnElement="Flow_1j3al1t">
<di:waypoint x="530" y="222" />
<di:waypoint x="530" y="120" />
<di:waypoint x="750" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0rg2b62_di" bpmnElement="Flow_0rg2b62">
<di:waypoint x="850" y="120" />
<di:waypoint x="946" y="120" />
<di:waypoint x="946" y="247" />
<di:waypoint x="1042" y="247" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1fu356n_di" bpmnElement="Flow_1fu356n">
<di:waypoint x="850" y="400" />
<di:waypoint x="946" y="400" />
<di:waypoint x="946" y="247" />
<di:waypoint x="1042" y="247" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
下面是写的几个接口调用过程,来完整执行流程。目前初版实现想法是,业务层还是有申请、审批表的,他们来关联流程实例编号,只引入流程服务来方便编排流程,因此中间过程参数也都存储在业务层,流程中参数只传递影响流程走向的参数,所以示例比较简单,但该想法并不一定是最终想法,只是对于下面接口设计的一些说明。
api接口调用流程
1.新增流程至指定用户审批
参数就不解释了,贴代码自行理解
FlowCreateResponse response = new FlowCreateResponse();
// 可选择的传入参数
// 可用来传递requestid
Map<String, Object> variables = new HashMap<>();
variables.put("creditor", request.getUserId());
ProcessInstance instance = runtimeService.startProcessInstanceByKey(
request.getProcessDefinitionKey(), variables);
response.setProcessInstanceId(instance.getProcessInstanceId());
// todo 如果第一个节点为用户节点,需要创建流程后即分配用户
TaskAssignRequest taskAssignRequest = new TaskAssignRequest();
taskAssignRequest.setAssigneeUserId(request.getAssigneeUserId());
taskAssignRequest.setOwnerUserId(request.getUserId());
taskAssignRequest.setProcessInstanceId(instance.getProcessInstanceId());
taskService.assignTask(taskAssignRequest);
return response;
2.查看指定用户的相关流程
只有用户1有流程
上代码
FlowListResponse flowListResponse = new FlowListResponse();
List<FlowInfo> flowInfoList = new ArrayList<>();
flowListResponse.setFlowInfoList(flowInfoList);
// 流程实例查询
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery()
.variableValueEquals("creditor", request.getUserId())
.processDefinitionKey(request.getProcessDefinitionKey())
.list();
if (CollUtil.isNotEmpty(processInstanceList)) {
for (ProcessInstance processInstance : processInstanceList) {
FlowInfo flowInfo = new FlowInfo();
flowInfo.setProcessInstanceId(processInstance.getId());
flowInfoList.add(flowInfo);
}
}
return flowListResponse;
3.查看指定用户的流程任务
用户2有待执行的任务
上代码
TaskListResponse response = new TaskListResponse();
List<Task> taskList = taskService.createTaskQuery()
.taskAssignee(request.getUserId())
.active().list();
List<TaskInfo> list = new ArrayList<>();
for (Task task : taskList) {
TaskInfo taskInfo = new TaskInfo();
taskInfo.setId(task.getId());
taskInfo.setProcessInstanceId(task.getProcessInstanceId());
taskInfo.setTaskName(taskInfo.getTaskName());
list.add(taskInfo);
}
response.setTaskList(list);
return response;
4.1提交流程至下一个用户审批
该种情况下,请求中的assigneeUserId不能为空
流程进入审批测试节点
4.2提交流程至自动节点
网关后根据某个指定参数来控制流程走向
可以看到配置的类已执行
5.1从审批测试节点继续提交,流程结束
5.2自动节点自动执行后,流程结束
遗留问题
-
异常场景测试
-
同步系统的用户角色表至流程服务
-
业务参数是否放到流程中去,还是流程只存放用于流程流转的关键数据
-
将flow服务集群部署后测试
-
流程图发布后直接更新不需要重启的控制
-
流程支持退回