服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Springboot整合工作流引擎Activiti之网关路由

Springboot整合工作流引擎Activiti之网关路由

2021-12-31 23:10Spring源码解读 Java教程

本篇主要演示复杂的审批流程的应用:排他网关路由的使用(Exclusive Gateway),希望能够帮助到你。

Springboot整合工作流引擎Activiti之网关路由

环境:Springboot2.3.12.RELEASE + Activiti7.1.0.M6

本篇主要演示复杂的审批流程的应用:排他网关路由的使用(Exclusive Gateway)

流程设计

Springboot整合工作流引擎Activiti之网关路由

审批说明:当员工请假天数小于等于3天时,部门经理审批,当部门经理同意flag==1流程结束,不同意flag==0流程返回到"员工请假"节点;当请假天数大于3天时,先由部门经理审批,再由总经理审批,当总经理同意flag==1流程结束,不同意flag==0流程返回到"员工请假"节点。

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <definitions xmlns="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"
  3.   <process id="holiday3" name="holiday3" isExecutable="true"
  4.     <startEvent id="startevent1" name="Start"></startEvent> 
  5.     <userTask id="usertask1" name="员工请假" activiti:assignee="${userId}"></userTask> 
  6.     <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway> 
  7.     <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow> 
  8.     <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow> 
  9.     <userTask id="usertask2" name="部门经理审批" activiti:assignee="${d_mgr}"></userTask> 
  10.     <sequenceFlow id="flow3" name="${days <=3}" sourceRef="exclusivegateway1" targetRef="usertask2"
  11.       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${days <=3}]]></conditionExpression> 
  12.     </sequenceFlow> 
  13.     <userTask id="usertask3" name="部门经理审批" activiti:assignee="${d_mgr}"></userTask> 
  14.     <userTask id="usertask4" name="总经理审批" activiti:assignee="${g_mgr}"></userTask> 
  15.     <sequenceFlow id="flow4" name="${days > 3}" sourceRef="exclusivegateway1" targetRef="usertask3"
  16.       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${days > 3}]]></conditionExpression> 
  17.     </sequenceFlow> 
  18.     <sequenceFlow id="flow5" sourceRef="usertask3" targetRef="usertask4"></sequenceFlow> 
  19.     <endEvent id="endevent1" name="End"></endEvent> 
  20.     <sequenceFlow id="flow6" name="${flag==1}" sourceRef="usertask2" targetRef="endevent1"
  21.       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==1}]]></conditionExpression> 
  22.     </sequenceFlow> 
  23.     <sequenceFlow id="flow7" name="${flag==1}" sourceRef="usertask4" targetRef="endevent1"
  24.       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==1}]]></conditionExpression> 
  25.     </sequenceFlow> 
  26.     <sequenceFlow id="flow8" name="${flag==0}" sourceRef="usertask2" targetRef="usertask1"
  27.       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==0}]]></conditionExpression> 
  28.     </sequenceFlow> 
  29.     <sequenceFlow id="flow9" name="${flag==0}" sourceRef="usertask4" targetRef="usertask1"
  30.       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==0}]]></conditionExpression> 
  31.     </sequenceFlow> 
  32.   </process> 
  33.   <bpmndi:BPMNDiagram id="BPMNDiagram_holiday3"
  34.     <bpmndi:BPMNPlane bpmnElement="holiday3" id="BPMNPlane_holiday3"
  35.       <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"
  36.         <omgdc:Bounds height="35.0" width="35.0" x="470.0" y="40.0"></omgdc:Bounds> 
  37.       </bpmndi:BPMNShape> 
  38.       <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"
  39.         <omgdc:Bounds height="55.0" width="105.0" x="435.0" y="120.0"></omgdc:Bounds> 
  40.       </bpmndi:BPMNShape> 
  41.       <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1"
  42.         <omgdc:Bounds height="40.0" width="40.0" x="467.0" y="260.0"></omgdc:Bounds> 
  43.       </bpmndi:BPMNShape> 
  44.       <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"
  45.         <omgdc:Bounds height="55.0" width="105.0" x="220.0" y="253.0"></omgdc:Bounds> 
  46.       </bpmndi:BPMNShape> 
  47.       <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3"
  48.         <omgdc:Bounds height="55.0" width="105.0" x="640.0" y="253.0"></omgdc:Bounds> 
  49.       </bpmndi:BPMNShape> 
  50.       <bpmndi:BPMNShape bpmnElement="usertask4" id="BPMNShape_usertask4"
  51.         <omgdc:Bounds height="55.0" width="105.0" x="880.0" y="253.0"></omgdc:Bounds> 
  52.       </bpmndi:BPMNShape> 
  53.       <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"
  54.         <omgdc:Bounds height="35.0" width="35.0" x="470.0" y="430.0"></omgdc:Bounds> 
  55.       </bpmndi:BPMNShape> 
  56.       <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"
  57.         <omgdi:waypoint x="487.0" y="75.0"></omgdi:waypoint> 
  58.         <omgdi:waypoint x="487.0" y="120.0"></omgdi:waypoint> 
  59.       </bpmndi:BPMNEdge> 
  60.       <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"
  61.         <omgdi:waypoint x="487.0" y="175.0"></omgdi:waypoint> 
  62.         <omgdi:waypoint x="487.0" y="260.0"></omgdi:waypoint> 
  63.       </bpmndi:BPMNEdge> 
  64.       <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"
  65.         <omgdi:waypoint x="467.0" y="280.0"></omgdi:waypoint> 
  66.         <omgdi:waypoint x="325.0" y="280.0"></omgdi:waypoint> 
  67.         <bpmndi:BPMNLabel> 
  68.           <omgdc:Bounds height="14.0" width="100.0" x="361.0" y="280.0"></omgdc:Bounds> 
  69.         </bpmndi:BPMNLabel> 
  70.       </bpmndi:BPMNEdge> 
  71.       <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"
  72.         <omgdi:waypoint x="507.0" y="280.0"></omgdi:waypoint> 
  73.         <omgdi:waypoint x="640.0" y="280.0"></omgdi:waypoint> 
  74.         <bpmndi:BPMNLabel> 
  75.           <omgdc:Bounds height="14.0" width="100.0" x="538.0" y="280.0"></omgdc:Bounds> 
  76.         </bpmndi:BPMNLabel> 
  77.       </bpmndi:BPMNEdge> 
  78.       <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"
  79.         <omgdi:waypoint x="745.0" y="280.0"></omgdi:waypoint> 
  80.         <omgdi:waypoint x="880.0" y="280.0"></omgdi:waypoint> 
  81.       </bpmndi:BPMNEdge> 
  82.       <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"
  83.         <omgdi:waypoint x="272.0" y="308.0"></omgdi:waypoint> 
  84.         <omgdi:waypoint x="272.0" y="447.0"></omgdi:waypoint> 
  85.         <omgdi:waypoint x="470.0" y="447.0"></omgdi:waypoint> 
  86.         <bpmndi:BPMNLabel> 
  87.           <omgdc:Bounds height="14.0" width="100.0" x="300.0" y="429.0"></omgdc:Bounds> 
  88.         </bpmndi:BPMNLabel> 
  89.       </bpmndi:BPMNEdge> 
  90.       <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7"
  91.         <omgdi:waypoint x="932.0" y="308.0"></omgdi:waypoint> 
  92.         <omgdi:waypoint x="932.0" y="447.0"></omgdi:waypoint> 
  93.         <omgdi:waypoint x="505.0" y="447.0"></omgdi:waypoint> 
  94.         <bpmndi:BPMNLabel> 
  95.           <omgdc:Bounds height="14.0" width="100.0" x="800.0" y="429.0"></omgdc:Bounds> 
  96.         </bpmndi:BPMNLabel> 
  97.       </bpmndi:BPMNEdge> 
  98.       <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8"
  99.         <omgdi:waypoint x="272.0" y="253.0"></omgdi:waypoint> 
  100.         <omgdi:waypoint x="272.0" y="147.0"></omgdi:waypoint> 
  101.         <omgdi:waypoint x="435.0" y="147.0"></omgdi:waypoint> 
  102.         <bpmndi:BPMNLabel> 
  103.           <omgdc:Bounds height="14.0" width="100.0" x="290.0" y="151.0"></omgdc:Bounds> 
  104.         </bpmndi:BPMNLabel> 
  105.       </bpmndi:BPMNEdge> 
  106.       <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9"
  107.         <omgdi:waypoint x="932.0" y="253.0"></omgdi:waypoint> 
  108.         <omgdi:waypoint x="932.0" y="147.0"></omgdi:waypoint> 
  109.         <omgdi:waypoint x="540.0" y="147.0"></omgdi:waypoint> 
  110.         <bpmndi:BPMNLabel> 
  111.           <omgdc:Bounds height="14.0" width="100.0" x="790.0" y="151.0"></omgdc:Bounds> 
  112.         </bpmndi:BPMNLabel> 
  113.       </bpmndi:BPMNEdge> 
  114.     </bpmndi:BPMNPlane> 
  115.   </bpmndi:BPMNDiagram> 
  116. </definitions> 

到此流程设计完成。

Service接口

  1. @Service 
  2. public class HolidayService { 
  3.  
  4.   private static final Logger logger = LoggerFactory.getLogger(HolidayService2.class); 
  5.   @Resource 
  6.   private RuntimeService runtimeService ; 
  7.   @Resource 
  8.   private TaskService taskService ; 
  9.   /** 
  10.    *  <p> 
  11.    *    设置assignee的取值,用户可以在界面上设置流程的执行人 
  12.    *  </p> 
  13.    *  <p>时间:2021年1月22日-下午8:30:39</p> 
  14.    * @author 爷爷 
  15.    * @param processDefinitionId  
  16.    * @return ProcessInstance 
  17.    */ 
  18.   public ProcessInstance startProcessInstanceAssignVariables(String processDefinitionId, Map<String, Object> variables) { 
  19.     Authentication.setAuthenticatedUserId((String)variables.get("assignee")) ; 
  20.     ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables); 
  21.     logger.info("流程定义ID: {}", processInstance.getProcessDefinitionId()); 
  22.     logger.info("流程实例ID: {}", processInstance.getId()); 
  23.     logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ; 
  24.     return processInstance ; 
  25.     } 
  26.   /** 
  27.    *  <p>执行任务</p> 
  28.    *  <p>时间:2021年1月24日-上午10:40:39</p> 
  29.    * @author 爷爷 
  30.    * @param variables 
  31.    * @param instanceId  
  32.    * @return void 
  33.    */ 
  34.   public void executionTask(Map<String, Object> variables, String instanceId) { 
  35.     Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult() ; 
  36.     if (task == null) { 
  37.       logger.error("任务【{}】不存在", instanceId) ; 
  38.       throw new RuntimeException("任务【" + instanceId + "】不存在") ; 
  39.     } 
  40.     // 注意这里一定要设置变量,否则流程中设置的表达式无法获取,如下图 
  41.     taskService.setVariables(task.getId(), variables); 
  42.     taskService.complete(task.getId(), variables) ; 
  43.   } 

方法的含义已经在代码中说明了。

Springboot整合工作流引擎Activiti之网关路由

Controller接口

  1. package com.pack.controller; 
  2.  
  3. import java.util.HashMap; 
  4. import java.util.List; 
  5. import java.util.Map; 
  6. import java.util.stream.Collectors; 
  7.  
  8. import javax.annotation.Resource; 
  9.  
  10. import org.activiti.engine.history.HistoricActivityInstance; 
  11. import org.activiti.engine.runtime.ProcessInstance; 
  12. import org.activiti.engine.task.Task; 
  13. import org.apache.commons.lang3.StringUtils; 
  14. import org.springframework.web.bind.annotation.GetMapping; 
  15. import org.springframework.web.bind.annotation.PathVariable; 
  16. import org.springframework.web.bind.annotation.RequestMapping; 
  17. import org.springframework.web.bind.annotation.RequestParam; 
  18. import org.springframework.web.bind.annotation.RestController; 
  19.  
  20. import com.pack.dto.ProcessDefinitionDTO; 
  21. import com.pack.dto.ProcessInstanceDTO; 
  22. import com.pack.dto.R; 
  23. import com.pack.task.HolidayService2; 
  24.  
  25. @RestController 
  26. @RequestMapping("/holidays2"
  27. public class HolidayController2 { 
  28.      
  29.   @Resource 
  30.   private HolidayService holidayService ; 
  31.      
  32.   /** 
  33.    *  <p>启动请假审批流程</p> 
  34.    *  <p>时间:2021年1月23日-上午10:32:55</p> 
  35.    * @author 爷爷 
  36.    * @param userId 
  37.    * @param processDefinitionId 流程定义Id 
  38.    * @return R 
  39.    */ 
  40.   @GetMapping("/start"
  41.   public R startProcess(String userId, String processDefinitionId) { 
  42.     Map<String, Object> variables = new HashMap<>() ; 
  43.     variables.put("userId", userId) ; 
  44.     ProcessInstance instance = holidayService.startProcessInstanceAssignVariables(processDefinitionId, variables) ; 
  45.     ProcessInstanceDTO dto = new ProcessInstanceDTO() ; 
  46.     dto.setInstanceId(instance.getId()) ; 
  47.     return R.success(dto) ; 
  48.   } 
  49.   /** 
  50.    *  <p> 
  51.    *    填写审批单 
  52.    *  </p> 
  53.    *  <p>时间:2021年1月23日-上午11:57:30</p> 
  54.    * @author 爷爷 
  55.    * @param Map取值如下 
  56.    * @param days 请假天数 
  57.    * @param explain 审批单说明 
  58.    * @param instanceId 流程实例ID 
  59.    * @param assignee 指定下一个流程执行人 
  60.    * @return R 
  61.    */ 
  62.   @GetMapping("/apply"
  63.   public R fillApply(@RequestParam Map<String, Object> variables) { 
  64.     String instanceId = (String) variables.remove("instanceId") ; 
  65.     if (StringUtils.isEmpty(instanceId)) { 
  66.       return R.failure("未知任务") ; 
  67.     } 
  68.     holidayService.executionTask(variables, instanceId); 
  69.     return R.success() ;  
  70.   } 

测试

启动流程

Springboot整合工作流引擎Activiti之网关路由

请假人处理

Springboot整合工作流引擎Activiti之网关路由

d_mgr:部门经理ID

days:3 (小于3天)

部门经理处理

Springboot整合工作流引擎Activiti之网关路由

flag:0 (不同意,驳回到员工申请)

查看act_hi_actinst表数据:

Springboot整合工作流引擎Activiti之网关路由

流程又进入到了“员工申请”节点

再次重复上面的流程,当走到部门经理时,将flag=1。

Springboot整合工作流引擎Activiti之网关路由

到此流程结束,当请求天数大于3天的处理过程与上面基本相同。

原文链接:https://www.toutiao.com/a7038841229978747422/

延伸 · 阅读

精彩推荐