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

[焦点] 时间:2025-11-05 06:42:00 来源:益强IT技术网 作者:域名 点击:176次

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

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

流程设计

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

<?整合xml version="1.0" encoding="UTF-8"?> <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">   <process id="holiday3" name="holiday3" isExecutable="true">     <startEvent id="startevent1" name="Start"></startEvent>     <userTask id="usertask1" name="员工请假" activiti:assignee="${userId}"></userTask>     <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>     <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>     <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow>     <userTask id="usertask2" name="部门经理审批" activiti:assignee="${d_mgr}"></userTask>     <sequenceFlow id="flow3" name="${days <=3}" sourceRef="exclusivegateway1" targetRef="usertask2">       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${days <=3}]]></conditionExpression>     </sequenceFlow>     <userTask id="usertask3" name="部门经理审批" activiti:assignee="${d_mgr}"></userTask>     <userTask id="usertask4" name="总经理审批" activiti:assignee="${g_mgr}"></userTask>     <sequenceFlow id="flow4" name="${days > 3}" sourceRef="exclusivegateway1" targetRef="usertask3">       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${days > 3}]]></conditionExpression>     </sequenceFlow>     <sequenceFlow id="flow5" sourceRef="usertask3" targetRef="usertask4"></sequenceFlow>     <endEvent id="endevent1" name="End"></endEvent>     <sequenceFlow id="flow6" name="${flag==1}" sourceRef="usertask2" targetRef="endevent1">       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==1}]]></conditionExpression>     </sequenceFlow>     <sequenceFlow id="flow7" name="${flag==1}" sourceRef="usertask4" targetRef="endevent1">       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==1}]]></conditionExpression>     </sequenceFlow>     <sequenceFlow id="flow8" name="${flag==0}" sourceRef="usertask2" targetRef="usertask1">       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==0}]]></conditionExpression>     </sequenceFlow>     <sequenceFlow id="flow9" name="${flag==0}" sourceRef="usertask4" targetRef="usertask1">       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag==0}]]></conditionExpression>     </sequenceFlow>   </process>   <bpmndi:BPMNDiagram id="BPMNDiagram_holiday3">     <bpmndi:BPMNPlane bpmnElement="holiday3" id="BPMNPlane_holiday3">       <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">         <omgdc:Bounds height="35.0" width="35.0" x="470.0" y="40.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">         <omgdc:Bounds height="55.0" width="105.0" x="435.0" y="120.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">         <omgdc:Bounds height="40.0" width="40.0" x="467.0" y="260.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">         <omgdc:Bounds height="55.0" width="105.0" x="220.0" y="253.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">         <omgdc:Bounds height="55.0" width="105.0" x="640.0" y="253.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="usertask4" id="BPMNShape_usertask4">         <omgdc:Bounds height="55.0" width="105.0" x="880.0" y="253.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">         <omgdc:Bounds height="35.0" width="35.0" x="470.0" y="430.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">         <omgdi:waypoint x="487.0" y="75.0"></omgdi:waypoint>         <omgdi:waypoint x="487.0" y="120.0"></omgdi:waypoint>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">         <omgdi:waypoint x="487.0" y="175.0"></omgdi:waypoint>         <omgdi:waypoint x="487.0" y="260.0"></omgdi:waypoint>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">         <omgdi:waypoint x="467.0" y="280.0"></omgdi:waypoint>         <omgdi:waypoint x="325.0" y="280.0"></omgdi:waypoint>         <bpmndi:BPMNLabel>           <omgdc:Bounds height="14.0" width="100.0" x="361.0" y="280.0"></omgdc:Bounds>         </bpmndi:BPMNLabel>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">         <omgdi:waypoint x="507.0" y="280.0"></omgdi:waypoint>         <omgdi:waypoint x="640.0" y="280.0"></omgdi:waypoint>         <bpmndi:BPMNLabel>           <omgdc:Bounds height="14.0" width="100.0" x="538.0" y="280.0"></omgdc:Bounds>         </bpmndi:BPMNLabel>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">         <omgdi:waypoint x="745.0" y="280.0"></omgdi:waypoint>         <omgdi:waypoint x="880.0" y="280.0"></omgdi:waypoint>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">         <omgdi:waypoint x="272.0" y="308.0"></omgdi:waypoint>         <omgdi:waypoint x="272.0" y="447.0"></omgdi:waypoint>         <omgdi:waypoint x="470.0" y="447.0"></omgdi:waypoint>         <bpmndi:BPMNLabel>           <omgdc:Bounds height="14.0" width="100.0" x="300.0" y="429.0"></omgdc:Bounds>         </bpmndi:BPMNLabel>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">         <omgdi:waypoint x="932.0" y="308.0"></omgdi:waypoint>         <omgdi:waypoint x="932.0" y="447.0"></omgdi:waypoint>         <omgdi:waypoint x="505.0" y="447.0"></omgdi:waypoint>         <bpmndi:BPMNLabel>           <omgdc:Bounds height="14.0" width="100.0" x="800.0" y="429.0"></omgdc:Bounds>         </bpmndi:BPMNLabel>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">         <omgdi:waypoint x="272.0" y="253.0"></omgdi:waypoint>         <omgdi:waypoint x="272.0" y="147.0"></omgdi:waypoint>         <omgdi:waypoint x="435.0" y="147.0"></omgdi:waypoint>         <bpmndi:BPMNLabel>           <omgdc:Bounds height="14.0" width="100.0" x="290.0" y="151.0"></omgdc:Bounds>         </bpmndi:BPMNLabel>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">         <omgdi:waypoint x="932.0" y="253.0"></omgdi:waypoint>         <omgdi:waypoint x="932.0" y="147.0"></omgdi:waypoint>         <omgdi:waypoint x="540.0" y="147.0"></omgdi:waypoint>         <bpmndi:BPMNLabel>           <omgdc:Bounds height="14.0" width="100.0" x="790.0" y="151.0"></omgdc:Bounds>         </bpmndi:BPMNLabel>       </bpmndi:BPMNEdge>     </bpmndi:BPMNPlane>   </bpmndi:BPMNDiagram> </definitions> 

到此流程设计完成。

Service接口

@Service public class HolidayService {   private static final Logger logger = LoggerFactory.getLogger(HolidayService2.class);   @Resource   private RuntimeService runtimeService ;   @Resource   private TaskService taskService ;   /**    *  <p>    *    设置assignee的工作取值,用户可以在界面上设置流程的流引路由执行人    *  </p>    *  <p>时间:2021年1月22日-下午8:30:39</p>    * @author 爷爷    * @param processDefinitionId     * @return ProcessInstance    */   public ProcessInstance startProcessInstanceAssignVariables(String processDefinitionId, Map<String, Object> 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 ;     }   /**    *  <p>执行任务</p>    *  <p>时间:2021年1月24日-上午10:40:39</p>    * @author 爷爷    * @param variables    * @param instanceId     * @return void    */   public void executionTask(Map<String, Object> 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) ;   } } 

方法的云南idc服务商含义已经在代码中说明了。

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 ;   /**    *  <p>启动请假审批流程</p>    *  <p>时间:2021年1月23日-上午10:32:55</p>    * @author 爷爷    * @param userId    * @param processDefinitionId 流程定义Id    * @return R    */   @GetMapping("/start")   public R startProcess(String userId,工作 String processDefinitionId) {     Map<String, Object> 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) ;   }   /**    *  <p>    *    填写审批单    *  </p>    *  <p>时间:2021年1月23日-上午11:57:30</p>    * @author 爷爷    * @param Map取值如下    * @param days 请假天数    * @param explain 审批单说明    * @param instanceId 流程实例ID    * @param assignee 指定下一个流程执行人    * @return R    */   @GetMapping("/apply")   public R fillApply(@RequestParam Map<String, Object> 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天的处理过程与上面基本相同。云服务器提供商

(责任编辑:系统运维)

    相关内容
    精彩推荐
    热门点击
    友情链接