好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

流程设计

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

<?xml version= "1.0"  encoding= "UTF-8" ?>  <definitions xmlns= "http://HdhCmsTestomg.org/spec/BPMN/20100524/MODEL"  xmlns:xsi= "http://HdhCmsTestw3.org/2001/XMLSchema-instance"  xmlns:xsd= "http://HdhCmsTestw3.org/2001/XMLSchema"  xmlns:activiti= "http://activiti.org/bpmn"  xmlns:bpmndi= "http://HdhCmsTestomg.org/spec/BPMN/20100524/DI"  xmlns:omgdc= "http://HdhCmsTestomg.org/spec/DD/20100524/DC"  xmlns:omgdi= "http://HdhCmsTestomg.org/spec/DD/20100524/DI"  typeLanguage= "http://HdhCmsTestw3.org/2001/XMLSchema"  expressionLanguage= "http://HdhCmsTestw3.org/1999/XPath"  targetNamespace= "http://HdhCmsTestxg测试数据" >    <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测试数据plete(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测试数据mons.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天的处理过程与上面基本相同。

原文链接:https://HdhCmsTesttoutiao测试数据/a7038841229978747422/

查看更多关于Springboot整合工作流引擎Activiti之网关路由的详细内容...

  阅读:15次