环境:Springboot2.3.12.RELEASE + Activiti7.1.0.M6
本篇主要演示复杂的审批流程的应用:排他网关路由的使用(Exclusive Gateway)
流程设计
审批说明:当员工请假天数小于等于3天时,部门经理审批,当部门经理同意flag==1流程结束,不同意flag==0流程返回到"员工请假"节点;当请假天数大于3天时,先由部门经理审批,再由总经理审批,当总经理同意flag==1流程结束,不同意flag==0流程返回到"员工请假"节点。
- "1.0" encoding="UTF-8"?>
"http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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.xg.com"> -
"holiday3" name="holiday3" isExecutable="true"> -
"startevent1" name="Start"> -
"usertask1" name="员工请假" activiti:assignee="${userId}"> -
"exclusivegateway1" name="Exclusive Gateway"> -
"flow1" sourceRef="startevent1" targetRef="usertask1"> -
"flow2" sourceRef="usertask1" targetRef="exclusivegateway1"> -
"usertask2" name="部门经理审批" activiti:assignee="${d_mgr}"> -
"flow3" name="${days <=3}" sourceRef="exclusivegateway1" targetRef="usertask2"> -
"tFormalExpression" > -
-
"usertask3" name="部门经理审批" activiti:assignee="${d_mgr}"> -
"usertask4" name="总经理审批" activiti:assignee="${g_mgr}"> -
"flow4" name="${days > 3}" sourceRef="exclusivegateway1" targetRef="usertask3"> -
"tFormalExpression" > 3}]]> -
-
"flow5" sourceRef="usertask3" targetRef="usertask4"> -
"endevent1" name="End"> -
"flow6" name="${flag==1}" sourceRef="usertask2" targetRef="endevent1"> -
"tFormalExpression" > -
-
"flow7" name="${flag==1}" sourceRef="usertask4" targetRef="endevent1"> -
"tFormalExpression" > -
-
"flow8" name="${flag==0}" sourceRef="usertask2" targetRef="usertask1"> -
"tFormalExpression" > -
-
"flow9" name="${flag==0}" sourceRef="usertask4" targetRef="usertask1"> -
"tFormalExpression" > -
-
-
"BPMNDiagram_holiday3" > -
"holiday3" id="BPMNPlane_holiday3"> -
"startevent1" id="BPMNShape_startevent1"> -
"35.0" width="35.0" x="470.0" y="40.0"> -
-
"usertask1" id="BPMNShape_usertask1"> -
"55.0" width="105.0" x="435.0" y="120.0"> -
-
"exclusivegateway1" id="BPMNShape_exclusivegateway1"> -
"40.0" width="40.0" x="467.0" y="260.0"> -
-
"usertask2" id="BPMNShape_usertask2"> -
"55.0" width="105.0" x="220.0" y="253.0"> -
-
"usertask3" id="BPMNShape_usertask3"> -
"55.0" width="105.0" x="640.0" y="253.0"> -
-
"usertask4" id="BPMNShape_usertask4"> -
"55.0" width="105.0" x="880.0" y="253.0"> -
-
"endevent1" id="BPMNShape_endevent1"> -
"35.0" width="35.0" x="470.0" y="430.0"> -
-
"flow1" id="BPMNEdge_flow1"> -
"487.0" y="75.0"> -
"487.0" y="120.0"> -
-
"flow2" id="BPMNEdge_flow2"> -
"487.0" y="175.0"> -
"487.0" y="260.0"> -
-
"flow3" id="BPMNEdge_flow3"> -
"467.0" y="280.0"> -
"325.0" y="280.0"> -
-
"14.0" width="100.0" x="361.0" y="280.0"> -
-
-
"flow4" id="BPMNEdge_flow4"> -
"507.0" y="280.0"> -
"640.0" y="280.0"> -
-
"14.0" width="100.0" x="538.0" y="280.0"> -
-
-
"flow5" id="BPMNEdge_flow5"> -
"745.0" y="280.0"> -
"880.0" y="280.0"> -
-
"flow6" id="BPMNEdge_flow6"> -
"272.0" y="308.0"> -
"272.0" y="447.0"> -
"470.0" y="447.0"> -
-
"14.0" width="100.0" x="300.0" y="429.0"> -
-
-
"flow7" id="BPMNEdge_flow7"> -
"932.0" y="308.0"> -
"932.0" y="447.0"> -
"505.0" y="447.0"> -
-
"14.0" width="100.0" x="800.0" y="429.0"> -
-
-
"flow8" id="BPMNEdge_flow8"> -
"272.0" y="253.0"> -
"272.0" y="147.0"> -
"435.0" y="147.0"> -
-
"14.0" width="100.0" x="290.0" y="151.0"> -
-
-
"flow9" id="BPMNEdge_flow9"> -
"932.0" y="253.0"> -
"932.0" y="147.0"> -
"540.0" y="147.0"> -
-
"14.0" width="100.0" x="790.0" y="151.0"> -
-
-
-
-
到此流程设计完成。
Service接口
- @Service
- public class HolidayService {
-
- private static final Logger logger = LoggerFactory.getLogger(HolidayService2.class);
- @Resource
- private RuntimeService runtimeService ;
- @Resource
- private TaskService taskService ;
-
- public ProcessInstance startProcessInstanceAssignVariables(String processDefinitionId, Map
variables) { - Authentication.setAuthenticatedUserId((String)variables.get("assignee")) ;
- ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
- logger.info("流程定义ID: {}", processInstance.getProcessDefinitionId());
- logger.info("流程实例ID: {}", processInstance.getId());
- logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ;
- return processInstance ;
- }
-
- public void executionTask(Map
variables, String instanceId) { - Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult() ;
- if (task == null) {
- logger.error("任务【{}】不存在", instanceId) ;
- throw new RuntimeException("任务【" + instanceId + "】不存在") ;
- }
- // 注意这里一定要设置变量,否则流程中设置的表达式无法获取,如下图
- taskService.setVariables(task.getId(), variables);
- taskService.complete(task.getId(), variables) ;
- }
- }
方法的含义已经在代码中说明了。
Controller接口
- package com.pack.controller;
-
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
-
- import javax.annotation.Resource;
-
- import org.activiti.engine.history.HistoricActivityInstance;
- import org.activiti.engine.runtime.ProcessInstance;
- import org.activiti.engine.task.Task;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
-
- import com.pack.dto.ProcessDefinitionDTO;
- import com.pack.dto.ProcessInstanceDTO;
- import com.pack.dto.R;
- import com.pack.task.HolidayService2;
-
- @RestController
- @RequestMapping("/holidays2")
- public class HolidayController2 {
-
- @Resource
- private HolidayService holidayService ;
-
-
- @GetMapping("/start")
- public R startProcess(String userId, String processDefinitionId) {
- Map
variables = new HashMap<>() ; - variables.put("userId", userId) ;
- ProcessInstance instance = holidayService.startProcessInstanceAssignVariables(processDefinitionId, variables) ;
- ProcessInstanceDTO dto = new ProcessInstanceDTO() ;
- dto.setInstanceId(instance.getId()) ;
- return R.success(dto) ;
- }
-
- @GetMapping("/apply")
- public R fillApply(@RequestParam Map
variables) { - String instanceId = (String) variables.remove("instanceId") ;
- if (StringUtils.isEmpty(instanceId)) {
- return R.failure("未知任务") ;
- }
- holidayService.executionTask(variables, instanceId);
- return R.success() ;
- }
- }
测试
启动流程
请假人处理
d_mgr:部门经理ID
days:3 (小于3天)
部门经理处理
flag:0 (不同意,驳回到员工申请)
查看act_hi_actinst表数据:
流程又进入到了“员工申请”节点
再次重复上面的流程,当走到部门经理时,将flag=1。
到此流程结束,当请求天数大于3天的处理过程与上面基本相同。