Activiti之 Exclusive Gateway

简介: 一、Exclusive Gateway   Exclusive Gateway(也称为XOR网关或更多技术基于数据的排他网关)经常用做决定流程的流转方向。当流程到达该网关的时候,所有的流出序列流到按照已定义好的顺序依次执行。

一、Exclusive Gateway

  Exclusive Gateway(也称为XOR网关或更多技术基于数据的排他网关)经常用做决定流程的流转方向。当流程到达该网关的时候,所有的流出序列流到按照已定义好的顺序依次执行。当序列流条件的求值结果为true(或没有条件集的时候,在概念上有定义一个“true”定义序列流),就会选择该序列继续的处理。Exclusive Gateway的图标就是菱形里面有一个X符合,如下所示:

  

  XML的代码为:

<exclusiveGateway id="exclusiveGw" name="Exclusive Gateway" />

<sequenceFlow id="flow2" sourceRef="exclusiveGw" targetRef="theTask1">
  <conditionExpression xsi:type="tFormalExpression">${input == 1}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow3" sourceRef="exclusiveGw" targetRef="theTask2">
  <conditionExpression xsi:type="tFormalExpression">${input == 2}</conditionExpression>
</sequenceFlow>

<sequenceFlow id="flow4" sourceRef="exclusiveGw" targetRef="theTask3">
  <conditionExpression xsi:type="tFormalExpression">${input == 3}</conditionExpression>
</sequenceFlow>

 二、示例

  本例子以请假流程为例,流程设计图如下图所示:

  

  当员工提出的请假时间大于2天的时候由总经理审批,当请假时间不大于2天的时候由经理审批。

  1、leave.bpmn内容如下: 

  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.activiti.org/test">
  3   <process id="leave" name="请假流程图" isExecutable="true">
  4     <documentation>请假流程图</documentation>
  5     <startEvent id="startevent1" name="Start"></startEvent>
  6     <endEvent id="endevent1" name="End"></endEvent>
  7     <!-- ${employeeId} 中的employeeId 在启动流程实例的时候,就设置employeeId变量。再根据employeeId获取员工请假任务,最后设置请假时间进行提交-->
  8     <userTask id="usertask1" name="员工请假" activiti:assignee="${employeeId}"></userTask>
  9     <userTask id="usertask2" name="经理审批" activiti:candidateGroups="manager"></userTask>
 10     <userTask id="usertask3" name="总经理审批" activiti:candidateGroups="boss"></userTask>
 11     <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
 12     <sequenceFlow id="flow2" name="${flag == true}" sourceRef="usertask2" targetRef="endevent1">
 13       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag == true}]]></conditionExpression>
 14     </sequenceFlow>
 15     <sequenceFlow id="flow3" name="${flag == true}" sourceRef="usertask3" targetRef="endevent1">
 16       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag == true}]]></conditionExpression>
 17     </sequenceFlow>
 18     <sequenceFlow id="flow4" name="${flag == false}" sourceRef="usertask2" targetRef="usertask1">
 19       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag == false}]]></conditionExpression>
 20     </sequenceFlow>
 21     <sequenceFlow id="flow5" name="${flag == false}" sourceRef="usertask3" targetRef="usertask1">
 22       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${flag == false}]]></conditionExpression>
 23     </sequenceFlow>
 24     <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
 25     <sequenceFlow id="flow6" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow>
 26     <sequenceFlow id="flow7" name="${day &lt;= 2}" sourceRef="exclusivegateway1" targetRef="usertask2">
 27       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${day <= 2}]]></conditionExpression>
 28     </sequenceFlow>
 29     <sequenceFlow id="flow8" name="${day &gt; 2}" sourceRef="exclusivegateway1" targetRef="usertask3">
 30       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${day > 2}]]></conditionExpression>
 31     </sequenceFlow>
 32   </process>
 33   <bpmndi:BPMNDiagram id="BPMNDiagram_leave">
 34     <bpmndi:BPMNPlane bpmnElement="leave" id="BPMNPlane_leave">
 35       <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
 36         <omgdc:Bounds height="35.0" width="35.0" x="355.0" y="48.0"></omgdc:Bounds>
 37       </bpmndi:BPMNShape>
 38       <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
 39         <omgdc:Bounds height="35.0" width="35.0" x="355.0" y="362.0"></omgdc:Bounds>
 40       </bpmndi:BPMNShape>
 41       <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
 42         <omgdc:Bounds height="55.0" width="105.0" x="320.0" y="112.0"></omgdc:Bounds>
 43       </bpmndi:BPMNShape>
 44       <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
 45         <omgdc:Bounds height="55.0" width="105.0" x="170.0" y="240.0"></omgdc:Bounds>
 46       </bpmndi:BPMNShape>
 47       <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
 48         <omgdc:Bounds height="55.0" width="105.0" x="480.0" y="242.0"></omgdc:Bounds>
 49       </bpmndi:BPMNShape>
 50       <bpmndi:BPMNShape bpmnElement="exclusivegateway1" id="BPMNShape_exclusivegateway1">
 51         <omgdc:Bounds height="40.0" width="40.0" x="352.0" y="247.0"></omgdc:Bounds>
 52       </bpmndi:BPMNShape>
 53       <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
 54         <omgdi:waypoint x="372.0" y="83.0"></omgdi:waypoint>
 55         <omgdi:waypoint x="372.0" y="112.0"></omgdi:waypoint>
 56       </bpmndi:BPMNEdge>
 57       <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
 58         <omgdi:waypoint x="222.0" y="295.0"></omgdi:waypoint>
 59         <omgdi:waypoint x="222.0" y="379.0"></omgdi:waypoint>
 60         <omgdi:waypoint x="355.0" y="379.0"></omgdi:waypoint>
 61         <bpmndi:BPMNLabel>
 62           <omgdc:Bounds height="14.0" width="100.0" x="183.0" y="309.0"></omgdc:Bounds>
 63         </bpmndi:BPMNLabel>
 64       </bpmndi:BPMNEdge>
 65       <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
 66         <omgdi:waypoint x="532.0" y="297.0"></omgdi:waypoint>
 67         <omgdi:waypoint x="532.0" y="379.0"></omgdi:waypoint>
 68         <omgdi:waypoint x="390.0" y="379.0"></omgdi:waypoint>
 69         <bpmndi:BPMNLabel>
 70           <omgdc:Bounds height="14.0" width="100.0" x="483.0" y="309.0"></omgdc:Bounds>
 71         </bpmndi:BPMNLabel>
 72       </bpmndi:BPMNEdge>
 73       <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
 74         <omgdi:waypoint x="222.0" y="240.0"></omgdi:waypoint>
 75         <omgdi:waypoint x="222.0" y="139.0"></omgdi:waypoint>
 76         <omgdi:waypoint x="320.0" y="139.0"></omgdi:waypoint>
 77         <bpmndi:BPMNLabel>
 78           <omgdc:Bounds height="14.0" width="100.0" x="170.0" y="191.0"></omgdc:Bounds>
 79         </bpmndi:BPMNLabel>
 80       </bpmndi:BPMNEdge>
 81       <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
 82         <omgdi:waypoint x="532.0" y="242.0"></omgdi:waypoint>
 83         <omgdi:waypoint x="532.0" y="139.0"></omgdi:waypoint>
 84         <omgdi:waypoint x="425.0" y="139.0"></omgdi:waypoint>
 85         <bpmndi:BPMNLabel>
 86           <omgdc:Bounds height="14.0" width="100.0" x="485.0" y="191.0"></omgdc:Bounds>
 87         </bpmndi:BPMNLabel>
 88       </bpmndi:BPMNEdge>
 89       <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
 90         <omgdi:waypoint x="372.0" y="167.0"></omgdi:waypoint>
 91         <omgdi:waypoint x="372.0" y="247.0"></omgdi:waypoint>
 92       </bpmndi:BPMNEdge>
 93       <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
 94         <omgdi:waypoint x="352.0" y="267.0"></omgdi:waypoint>
 95         <omgdi:waypoint x="275.0" y="267.0"></omgdi:waypoint>
 96         <bpmndi:BPMNLabel>
 97           <omgdc:Bounds height="14.0" width="100.0" x="283.0" y="247.0"></omgdc:Bounds>
 98         </bpmndi:BPMNLabel>
 99       </bpmndi:BPMNEdge>
100       <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
101         <omgdi:waypoint x="392.0" y="267.0"></omgdi:waypoint>
102         <omgdi:waypoint x="480.0" y="269.0"></omgdi:waypoint>
103         <bpmndi:BPMNLabel>
104           <omgdc:Bounds height="14.0" width="100.0" x="400.0" y="247.0"></omgdc:Bounds>
105         </bpmndi:BPMNLabel>
106       </bpmndi:BPMNEdge>
107     </bpmndi:BPMNPlane>
108   </bpmndi:BPMNDiagram>
109 </definitions>

  2、测试类LeaveTest代码如下:

  1 package com.shh.test;
  2 
  3 import java.util.HashMap;
  4 import java.util.List;
  5 import java.util.Map;
  6 
  7 import org.activiti.engine.HistoryService;
  8 import org.activiti.engine.ProcessEngine;
  9 import org.activiti.engine.ProcessEngineConfiguration;
 10 import org.activiti.engine.RepositoryService;
 11 import org.activiti.engine.RuntimeService;
 12 import org.activiti.engine.TaskService;
 13 import org.activiti.engine.history.HistoricProcessInstanceQuery;
 14 import org.activiti.engine.task.Task;
 15 import org.junit.Before;
 16 import org.junit.Test;
 17 /**
 18  * 请假流程
 19  */
 20 public class LeaveTest {
 21     ProcessEngine processEngine = null;
 22     RepositoryService repositoryService = null;
 23     RuntimeService runtimeService = null;
 24     TaskService taskService = null; 
 25 
 26     /**
 27      * 加载配置文件
 28      */
 29     @Before
 30     public void init() {
 31         processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml")
 32                 .buildProcessEngine();
 33         repositoryService = processEngine.getRepositoryService();
 34         runtimeService = processEngine.getRuntimeService();
 35         taskService = processEngine.getTaskService();
 36     }
 37 
 38     /**
 39      * 部署流程定义
 40      */
 41     @Test
 42     public void deploy(){
 43         repositoryService.createDeployment().addClasspathResource("diagrams/leave.bpmn").deploy();
 44         System.out.println("***************部署流程定义完成***************");
 45     }
 46     
 47     /**
 48      * 启动一个请假流程
 49      */
 50     @Test
 51     public void start() {
 52         Map<String, Object> variables = new HashMap<String, Object>();
 53         variables.put("employeeId", "Kermit"); //请假人
 54         String processId = runtimeService.startProcessInstanceByKey("leave", variables).getId();
 55         System.out.println("***************启动一个请假流程完成***************" + processId);
 56     }
 57 
 58     /**
 59      * 提交请假申请
 60      */
 61     @Test
 62     public void apply(){
 63         System.out.println("***************提交请假申请开始***************");
 64         List<Task> tasks = taskService.createTaskQuery().taskAssignee("Kermit").list();
 65         System.out.println(tasks.size());
 66         for (Task task : tasks) {
 67             System.out.println("Kermit的任务taskname:" + task.getName() + ",id:" + task.getId());
 68             taskService.setVariable(task.getId(), "day", 4);//设置请假天数
 69             taskService.complete(task.getId());//完成任务  
 70             System.out.println("请假4 天");
 71         }
 72         System.out.println("***************提交请假申请完成***************");
 73     }
 74     
 75     @Test
 76     public void step2manager() {
 77         System.out.println("***************经理组审批流程开始***************");
 78         List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("manager").list();// 经理组的任务
 79         System.out.println("经理组的任务:" + tasks.size());
 80         for (Task task : tasks) {
 81             System.out.println("经理组的任务taskname:" + task.getName() + ",id:" + task.getId());
 82             taskService.claim(task.getId(), "李四");//申领任务 
 83             taskService.setVariable(task.getId(), "flag", false);//true批准,false不批准
 84             Object applyUser = taskService.getVariable(task.getId(), "employeeId");
 85             Object day = taskService.getVariable(task.getId(), "day");
 86             System.out.println(String.format("%s请假%s天", applyUser, day));
 87             taskService.complete(task.getId());//完成任务 
 88         }
 89         System.out.println("***************经理组审批流程结束***************");
 90     }
 91     
 92     @Test
 93     public void step2Boss() {
 94         System.out.println("***************总经理组审批流程开始***************");
 95         List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("boss").list();// 总经理组的任务
 96         System.out.println("总经理组的任务:" + tasks.size());
 97         for (Task task : tasks) {
 98             System.out.println("manager的任务taskname:" + task.getName() + ",id:" + task.getId());
 99             taskService.claim(task.getId(), "王五");//申领任务 
100             taskService.setVariable(task.getId(), "flag", true);//true批准,false不批准
101             Object applyUser = taskService.getVariable(task.getId(), "employeeId");
102             Object day = taskService.getVariable(task.getId(), "day");
103             System.out.println(String.format("%s请假%s天", applyUser, day));
104             taskService.complete(task.getId());//完成任务 
105         }
106         System.out.println("***************总经理组审批流程结束***************");
107     }
108 }    

  依次运行deploy()、start()、apply()方法之后,因为申请的请假天数为4天,所以流程已经到了总经理角色,此时运行step2Boss()方法,一个完整的请假流程就已经完成。运行结果如下图所示:

  

  也可对代码进行修改,总经理不批准

 taskService.setVariable(task.getId(), "flag", false);

 流程就回到员工那里,员工继续申请,设置天数为2
taskService.setVariable(task.getId(), "day", 4);//设置请假天数

  此时流程到达经理角色,经理批准,流程也就结束

 taskService.setVariable(task.getId(), "flag", true);
目录
相关文章
|
XML Java API
使用 XDocReport 将 .docx 文件转换为 .pdf 文件
本文介绍如何使用 XDocReport 库在 Java 中将 Word 文件转换为 PDF 文件
5956 0
|
5月前
|
人工智能 缓存 监控
GitHub 8k star!Portkey AI Gateway 如何帮你3行代码接入1600+ LLM,实现成本、可靠性与安全三赢?
Portkey AI Gateway 是一个轻量级、高速、安全的中间层,帮助应用对接多模态 AI 模型,统一管理,快速落地。支持超1600款语言、视觉、音频、图像模型,通过 1 个 API 接口实现快速、可靠、安全的模型路由。具备智能路由、自动重试、缓存机制、合规控制等功能,助力企业高效构建 AI 应用。
310 0
|
8月前
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,处理前后端日期交互是一个常见问题。本文通过 **@DateTimeFormat** 和 **@JsonFormat** 两个注解,详细讲解了如何解析前端传来的日期字符串以及以指定格式返回日期数据。文章从实际案例出发,结合代码演示两者的使用场景与注意事项,解决解析失败、时区偏差等问题,并提供全局配置与局部注解的实践经验。帮助开发者高效应对日期时间格式化需求,提升开发效率。
2117 2
|
设计模式 小程序 前端开发
通义灵码一周年:通义灵码,一款适合零基础初学者的编码搭子
本文介绍了作者作为前端开发工程师,通过体验通义灵码的@workspace和@terminal功能,从零基础初学者的角度出发,逐步掌握编程的过程。文章详细描述了安装通义灵码的方法、如何通过提问学习项目结构和功能、以及如何使用@terminal执行和启动项目。最终,作者表示通过这些工具,他已经顺利入门编程,并将继续探索更多功能。
680 1
通义灵码一周年:通义灵码,一款适合零基础初学者的编码搭子
|
11月前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
774 8
|
数据采集 自然语言处理 搜索推荐
淘宝评价API接口的开发与应用
在数字化商业时代,数据成为企业提升竞争力的关键资源。淘宝作为电商巨头,其商品评论数据极具价值。本文详细介绍了淘宝评价API接口的开发流程与应用场景,从注册账号、获取密钥到实际调用和数据解析,再到商品分析、店铺管理、个性化推荐等多个方面,全面解析了技术细节与实践方法,为企业和开发者提供了宝贵的技术支持和数据资源。
712 0
|
机器学习/深度学习 大数据 vr&ar
我在哪些场景下使用过AMD实例,具体都做了什么事
我在哪些场景下使用过AMD实例,具体都做了什么事
407 6
|
机器学习/深度学习 监控 安全
2024年中测评:5款实用的消防巡检系统
本文对市面上5款主流的消防巡检系统进行了深入的测评分析,包括草料二维码、橙子巡检、巡检卫士等等。
|
SQL 数据库
DBeaver执行sql文件
本文介绍了DBeaver这款支持多种数据库的通用数据库管理工具和SQL客户端,它具备查看数据库结构、执行SQL查询和脚本、浏览和导出数据等功能。
1728 1
DBeaver执行sql文件
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
1453 3