java 使用 activiti 工作流的基本用法

112 阅读19分钟
版本信息:
    idea:2021.3.1
    java:17
    mysql:8.0.36
    maven:3.6.3
使用插件:
    Activiti BPMN visualizer
    JBoss jBPM

前提

需要安装如下插件

image.png

目录

  1. 创建数据库
  2. 创建 maven 工程
  3. 添加依赖
  4. 创建activiti.cfg.xml文件
  5. 创建工具类,生成数据库表
  6. 启动项目,生成数据表
  7. 使用 bpmn 画流程图
  8. 流程部署
  9. 启动流程实例
  10. 查询个人待执行任务
  11. 完成个人任务
  12. 查询流程定义
  13. 删除流程部署信息
  14. 下载资源文件
  15. 流程历史信息查看
  16. 流程添加业务key
  17. 流程实例的挂起和激活
  18. 通过uel格式动态地为每一个流程节点设置assignee
  19. 监听器分配
  20. 在启动流程的时候定义流程变量
  21. 在完成任务的时候定义流程变量
  22. 使用组任务办理流程
  23. 排他网关
  24. 并行网关
  25. 包含网关
  26. 代码demo

一、创建数据库

create database activity DEFAULT CHARACTER SET utf8mb4

二、创建 maven 工程

image.png

image.png

三、添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yuqn</groupId>
    <artifactId>activityPro</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <activiti.version>7.0.0.Beta1</activiti.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn模型处理-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn转换-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn json数据转换-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- bpmn布局-->
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- activity 云支持-->
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-services-api</artifactId>
            <version>${activiti.version}</version>
        </dependency>
        <!-- mysql驱动-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!-- mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.13</version>
        </dependency>
        <!-- 连接池依赖-->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- log start-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>

</project>

四、创建activiti.cfg.xml文件

需要在 resource 目录下创建 activiti.cfg.xml 文件,内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 在默认方式下,bean的id固定为processEngineConfiguration-->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- 配置数据库相关信息-->
        <!-- 数据库驱动-->
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
        <!-- 数据库连接-->
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3307/activity-db?characterEncoding=utf-8"/>
        <!-- 数据库用户-->
        <property name="jdbcUsername" value="root"/>
        <!-- 数据库密码-->
        <property name="jdbcPassword" value="your_password"/>
        <!-- activiti 数据库表生成的策略 true-如果数据库中已经存在相应的表,那么直接使用,如果不存在就会创建-->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>

</beans>

五、创建工具类,生成数据库表

/**
 * @author: yuqn
 * @Date: 2024/4/28 17:41
 * @description:
 * 使用activiti提供的默认方式来创建mysql的表
 * @param: null
 * @return: null
 */
@Test
public void testCreateDbTable(){
    // 需要使用activiti提供的工具类ProcessEngines,使用getDefaultProcessEngine方法
    // getDefaultProcessEngine方法会默认从resources下读取activiti.cfg.xml文件
    // 创建processEngine时,就会创建mysql表
    ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
    System.out.println(defaultProcessEngine);
}

六、启动项目,生成数据表

image.png

七、使用 bpmn 画流程图

1、创建 bpmn 文件

image.png

2、右击文件打开视图

image.png

3、画流程图

image.png

要指定每一个的name和assigne属性:

image.png

image.png

image.png

image.png

image.png

4、流程定义

4.1、将上述bpmn文件改为xml后缀,并且右键 dragrams 转为流程

image.png

image.png

4.2、导出png文件

image.png

4.3、转回bpmn文件

八、流程部署

将流程存到数据库,通过提供的接口,上传信息,代码如下:

@Test
public void testDeployment(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RepositoryServoie
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、使用service进行流程部署,定义一个流程的名字,把bpmn和png部署到数据中
    Deployment deploy = repositoryService.createDeployment()
            .name("出差信息")
            .addClasspathResource("bpmn/evection.bpmn20.xml")
            .addClasspathResource("bpmn/evection.png")
            .deploy();
    // 4、输出部署信息
    System.out.println("流程部署id=" + deploy.getId());
    System.out.println("流程部署名字=" + deploy.getName());

}

image.png

部署成功后,操作了四张表,分别是 act_ge_bytearray、act_ge_property、act_re_deployment、act_re_procdef 。

1、act_re_deployment:每次部署都会新增一条记录

2、act_re_procdef:流程定义表

3、act_ge_bytearray:流程资源表

8.1 通过zip模式上传资源

/**
 * @author: yuqn
 * @Date: 2024/4/29 23:52
 * @description:
 * 通过zip压缩包部署
 * @param: null
 * @return: null
 */
@Test
public void deployProcessByZip(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RepositoryServoie
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、流程部署
    // 读取资源包文件,构成inputStream
    InputStream inputStream = this.getClass()
            .getClassLoader()
            .getResourceAsStream("bpmn/evection.zip");
    // 用inputStream构成zipinputstream
    ZipInputStream zipInputStream = new ZipInputStream(inputStream);
    // 使用压缩包流程进行流程的部署
    Deployment deploy = repositoryService.createDeployment()
            .addZipInputStream(zipInputStream)
            .deploy();
    System.out.println("流程部署id= " + deploy.getId());
    System.out.println("流程部署名称= " + deploy.getName());
}

九、启动流程实例

/**
 * @author: yuqn
 * @Date: 2024/4/29 17:22
 * @description:
 * 启动流程实例
 * act_hi_actinst 流程实例执行历史
 * act_hi_identitylink 流程的参与用户历史信息
 * act_hi_procinst 流程实例历史信息
 * act_hi_taskinst 流程任务历史信息
 * act_ru_execution 流程正在执行信息
 * act_ru_identitylink 流程的参与用户信息
 * act_ru_task 任务信息
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 3、根据流程定义的id启动流程
    ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
    // 4、输出内容
    System.out.println("流程定义id:" + instance.getProcessDefinitionId());
    System.out.println("流程实例id:" + instance.getId());
    System.out.println("当前活动的id:" + instance.getActivityId());
}

十、查询个人待执行任务

/**
 * @author: yuqn
 * @Date: 2024/4/29 18:18
 * @description:
 * 查询个人待执行任务
 * @param: null
 * @return: null
 */
@Test
public void testFindPersonalTaskList(){
    // 1、获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取taskService
    TaskService taskService = processEngine.getTaskService();
    // 3、根据 流程key 和 任务负责人 查询任务
    List<Task> taskList = taskService.createTaskQuery()
            .processDefinitionKey("myEvection")
            .taskAssignee("张三")
            .list();
    // 4、输出
    for (Task task : taskList) {
        System.out.println("流程实例id=" + task.getProcessInstanceId());
        System.out.println("任务id=" + task.getId());
        System.out.println("任务负责人=" + task.getAssignee());
        System.out.println("任务名称=" + task.getName());
    }
}

十一、完成个人任务

/**
 * @author: yuqn
 * @Date: 2024/4/29 22:54
 * @description:
 * 完成个人任务
 */
@Test
public void completTask(){
    // 1、获取控制流引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取TaskService
    TaskService taskService = processEngine.getTaskService();

    // 3、根据任务id完成个人任务
    // taskService.complete("2505");

//        // 3、获取jerry-myevection对应任务
//        Task task = taskService.createTaskQuery()
//                .processDefinitionKey("myEvection")
//                .taskAssignee("jerry")
//                .singleResult();
//        // 完成jerry的任务
//        taskService.complete(task.getId());

//        // 3、获取jack-myevection对应任务
//        Task task = taskService.createTaskQuery()
//                .processDefinitionKey("myEvection")
//                .taskAssignee("jack")
//                .singleResult();
//        // 完成jerry的任务
//        taskService.complete(task.getId());

        // 3、获取rose-myevection对应任务
//        Task task = taskService.createTaskQuery()
//                .processDefinitionKey("myEvection")
//                .taskAssignee("rose")
//                .singleResult();
//        // 完成jerry的任务
//        taskService.complete(task.getId());
    }

十二、查询流程定义

/**
 * @author: yuqn
 * @Date: 2024/5/5 23:41
 * @description:
 * 查询流程定义
 * @param: null
 * @return: null
 */
@Test
public void queryProcessDefinition(){
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取repositoryservice
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 获取processdifinitionquery对象
    ProcessDefinitionQuery definitionQuery = repositoryService.createProcessDefinitionQuery();
    //查询当前所有的流程定义,返回流程定义信息的集合
    // processDefinitionKey(里路程定义的key)
    // orderbyprocessdefinitionversion进行排序
    // desc 倒序
    // list 查询出所有内容
    List<ProcessDefinition> definitionList = definitionQuery.processDefinitionKey("myEvection")
            .orderByProcessDefinitionVersion()
            .desc()
            .list();
    // 输出信息
    for (ProcessDefinition processDefinition : definitionList) {
        System.out.println("流程定义id = " + processDefinition.getId());
        System.out.println("流程定义名称 = " + processDefinition.getName());
        System.out.println("流程定义key = " + processDefinition.getKey());
        System.out.println("流程定义版本 = " + processDefinition.getVersion());
        System.out.println("流程部署的id = " + processDefinition.getDeploymentId());
    }
}

十三、删除流程部署信息

/**
 * @author: yuqn
 * @Date: 2024/5/5 23:41
 * @description:
 * 删除流程部署信息
 * @param: null
 * @return: null
 * 当前流程如果没有全部完成,想要删除的话需要使用特殊方式,原理就是 级联删除
 */
@Test
public void deleteDeployMent(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 通过引擎来获取 RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 通过部署id删除流程部署信息
    String deploymentId = "15001";

    // 非级联删除
    //repositoryService.deleteDeployment(deploymentId);

    // 级联删除,流程没有完全完成也能删除
    repositoryService.deleteDeployment(deploymentId,true);
}

需要添加依赖,用于文件转换:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

十四、下载资源文件

/**
 * @author: yuqn
 * @Date: 2024/5/9 16:41
 * @description:
 * 下载资源文件
 * 方案一:使用activiti提供的api下载资源文件,保存到文件目录
 * 方案二:自己写代码从数据库中下载文件
 * @param: null
 * @return: null
 */
@Test
public void getDeployment() throws IOException {
    // 1、得到引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取api、repositoryservice
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、获取查询对象 processdefinitionquery,查询流程定义信息
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey("myEvection")
            .singleResult();
    // 4、通过流程定义信息,获取部署id
    String deploymentId = processDefinition.getDeploymentId();
    // 5、通过repositoryservice,传递部署id参数,读取资源信息(png和bpmn)
    // 5.1、获取png图片的流
    String pngName = processDefinition.getDiagramResourceName();
    InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
    // 5.2、获取bpmn的流
    String bpmnName = processDefinition.getResourceName();
    InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);
    // 6、构造outputstream流
    File pngFile = new File("E:\\myJavaProject/activityPro/evectionflow01.png");
    File bpmnFile = new File("E:\\myJavaProject/activityPro/evectionflow01.bpmn");
    FileOutputStream pngOutStream = new FileOutputStream(pngFile);
    FileOutputStream bpmnOutStream = new FileOutputStream(bpmnFile);
    // 7、输入流、输出流的转换
    IOUtils.copy(pngInput,pngOutStream);
    IOUtils.copy(bpmnInput,bpmnOutStream);
    // 8、关闭流
    pngOutStream.close();
    bpmnOutStream.close();
    pngInput.close();
    bpmnInput.close();
}

十五、流程历史信息查看

/**
 * @author: yuqn
 * @Date: 2024/5/9 17:37
 * @description:
 * 流程历史信息查看
 * @param: null
 * @return: null
 */
@Test
public void findHistoryInfo(){
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取Historyservice
    HistoryService historyService = processEngine.getHistoryService();
    // 获取actinst表的查询对象
    HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
    // 查询actinst表
    instanceQuery.processInstanceId("2501");
    instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
    // 查询所有内容
    List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
    // 输出
    for (HistoricActivityInstance hi : activityInstanceList) {
        System.out.println(hi.getActivityId());
        System.out.println(hi.getActivityName());
        System.out.println(hi.getProcessDefinitionId());
        System.out.println(hi.getProcessInstanceId());
        System.out.println("<------------------------------->");
    }
}

十六、流程添加业务key

给每一个流程实例关联一个业务key,该key为其他业务表的id,这样可以查看该实例除了activiti提供的信息外的其他信息。

/**
 * @author: yuqn
 * @Date: 2024/5/10 16:09
 * @description:
 * 添加业务key到activiti表
 * @param: null
 * @return: null
 */
@Test
public void addBusinessKey(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 启动流程的过程中,添加businesskey
    // 第一个参数:流程定义的key
    // 第二个参数:业务表id
    ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection", "1002");
    // 输出
    System.out.println("instance.getBusinessKey() = " + instance.getBusinessKey());
}

十七、流程实例的挂起和激活

17.1、全部流程实例的挂起和激活

/**
 * @author: yuqn
 * @Date: 2024/5/10 16:50
 * @description:
 * 全部流程实例的挂起和激活
 * suspend暂停
 * @param: null
 * @return: null
 */
@Test
public void suspendAllProcessInstance(){
    // 1、获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取repositoryservice
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、查询流程定义
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey("myEvection")
            .singleResult();
    // 4、获取读取流程定义的实力是否都是挂起状态
    boolean suspended = processDefinition.isSuspended();
    // 5、获取流程定义的id
    String definitionId = processDefinition.getId();
    if(suspended){
        /*
        * 6、如果是挂起状态,改为激活状态
        * 参数一:流程定义id
        * 参数二:是否激活
        * 参数三:激活时间
        * */
        repositoryService.activateProcessDefinitionById(definitionId,true,null);
        System.out.println("流程定义id:" + definitionId + "已激活");
    }else{
        /*
         * 7、如果是激活状态,改为挂起状态
         * 参数一:流程定义id
         * 参数二:是否暂停
         * 参数三:暂停时间
         * */
        repositoryService.suspendProcessDefinitionById(definitionId,true,null);
        System.out.println("流程定义id:" + definitionId + "已挂起");
    }
}

17.2、单个流程实例的挂起和激活

/**
 * @author: yuqn
 * @Date: 2024/5/10 16:50
 * @description:
 * 单个流程实例的挂起和激活
 * suspend暂停
 * @param: null
 * @return: null
 */
@Test
public void suspendSingleProcessInstance(){
    // 1、获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 3、通过runtimeservice获取流程实例对象
    ProcessInstance instance = runtimeService.createProcessInstanceQuery()
            .processInstanceId("30001")
            .singleResult();
    // 4、得到当前流程实例的暂停状态
    boolean suspended = instance.isSuspended();
    // 5、获取流程实例id
    String instanceId = instance.getId();
    // 6、如果已经暂停,执行激活操作
    if(suspended){
        runtimeService.activateProcessInstanceById(instanceId);
        System.out.println("流程实例id:" + instanceId + "已经激活");
    }else{
        // 7、如果已经激活,执行暂停操作
        runtimeService.suspendProcessInstanceById(instanceId);
        System.out.println("流程实例id:" + instanceId + "已经暂停");
    }
}

十八、通过uel格式动态地为每一个流程节点设置assignee

1-17的例子所介绍的流程中,每一个节点的assignee都是固定的,如:张三、jerry 等等,在实际开发中,负责每一个工作流程的人并不是固定的,所以可以通过uel设置 Assignee 值为变量,使之更具有灵活性,用法如下:${变量值} ,该方法相当于将原本固定的负责人改为一个占位符。

image.png

image.png

image.png

image.png

18.1、部署流程

/**
 * @author: yuqn
 * @Date: 2024/5/11 15:47
 * @description:
 * 第四部分:基于assignee uel模式测试模块
 * @version: 1.0
 */
public class TestAssigneeUel {
    /**
     * @author: yuqn
     * @Date: 2024/4/29 23:52
     * @description:
     * 部署流程
     * @param: null
     * @return: null
     */
    @Test
    public void testDeployment(){
        // 1、创建processEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2、获取RepositoryServoie
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3、使用service进行流程部署,定义一个流程的名字,把bpmn和png部署到数据中
        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请流程-uel")
                .addClasspathResource("bpmn/evection-uel.bpmn20.xml")
                .addClasspathResource("bpmn/evection-uel.png")
                .deploy();
        // 4、输出部署信息
        System.out.println("流程部署id=" + deploy.getId());
        System.out.println("流程部署名字=" + deploy.getName());
    }

18.2、启动流程引擎

/**
 * @author: yuqn
 * @Date: 2024/5/11 15:52
 * @description:
 * 启动流程引擎
 * @param: null
 * @return: null
 */
@Test
public void startAssigneeUel(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 设定assignee的值,用来替代uel表达式
    Map<String,Object> assigneeMap = new HashMap<>();
    assigneeMap.put("assignee0","张三");
    assigneeMap.put("assignee1","李经理");
    assigneeMap.put("assignee2","王总经理");
    assigneeMap.put("assignee3","赵财务");
    // 启动流程实例
    ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection1",assigneeMap);
    // 输出
    System.out.println("流程定义id:" + instance.getProcessDefinitionId());
    System.out.println("流程实例id:" + instance.getId());
    System.out.println("当前活动的id:" + instance.getActivityId());
}

十九、监听器分配

监听器不可用,该插件目前没有提供监听器功能!!!!!!!!!!!!!

每一个流程节点可以有多个负责人,可以使用监听器分配,在流程设计时就不需要指定assignee值了,启动流程的时候通过监听器自动分配。

image.png

image.png

image.png

创建监听器,每次启动都会通过监听器执行

/**
 * @author: yuqn
 * @Date: 2024/5/11 16:42
 * @description:
 * 监听器
 * @version: 1.0
 */
public class MyTaskListener implements TaskListener {
    /**
     * @author: yuqn
     * @Date: 2024/5/11 16:43
     * @description:
     * 指定负责人
     * @param: delegateTask
     */
    @Override
    public void notify(DelegateTask delegateTask) {
        System.out.println("*****************");
        System.out.println("delegateTask.getName() = " + delegateTask.getName());
        System.out.println("delegateTask.getEventName() = " + delegateTask.getEventName());
        // 如果当前是 创建申请 并且是 create 事件 ,则设置为张三
        if ("创建申请".equals(delegateTask.getName()) &&
                "start".equals(delegateTask.getEventName())){
            delegateTask.setAssignee("张三");
        }
    }
}

部署和启动:

/**
 * @author: yuqn
 * @Date: 2024/4/29 23:52
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RepositoryServoie
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、使用service进行流程部署,定义一个流程的名字,把bpmn和png部署到数据中
    Deployment deploy = repositoryService.createDeployment()
            .name("测试监听器")
            .addClasspathResource("bpmn/evection-listen.bpmn20.xml")
            .deploy();
    // 4、输出部署信息
    System.out.println("流程部署id=" + deploy.getId());
    System.out.println("流程部署名字=" + deploy.getName());
}

@Test
public void startDemoListener(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 启动流程实例
    runtimeService.startProcessInstanceByKey("evection-listen");
}

二十、在启动流程的时候定义流程变量

场景:如果请假出差时间小于三天,则经理审批后直接由财务审批;如果请假出差时间大于三天,则经理审批后由总经理审批,最后再由财务审批。

以上场景中的三天就是流程变量,如下图:

image.png

20.1、画流程图,并且给每一个流程节点设置assignee值和定义流程变量(这里以 ${evection.num} 为例子)

image.png

image.png

image.png

image.png

image.png

image.png

image.png

20.2、创建 pojo 类

原理:在启动流程的时候,会将pojo对象一同作为参数,在完成任务时,就可以拿到 pojo.num 的值了,

该 pojo 需要实现 Serializable 接口完成序列化。

/**
 * @author: yuqn
 * @Date: 2024/5/12 0:49
 * @description:
 * 出差申请中的流程变量
 * @version: 1.0
 */
public class Evection implements Serializable {
    /**
     * 主键id
     */
    private Long id;
    /**
     * 出差单名字
     */
    private String evectionName;
    /**
    * 出差天数
    */
    private Double num;
    /**
     * 出差开始时间
     */
    private Date beginDate;
    /**
     * 出差结束时间
     */
    private Date endDate;
    /**
     * 出差目的地
     */
    private String destination;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getEvectionName() {
        return evectionName;
    }

    public void setEvectionName(String evectionName) {
        this.evectionName = evectionName;
    }

    public Double getNum() {
        return num;
    }

    public void setNum(Double num) {
        this.num = num;
    }

    public Date getBeginDate() {
        return beginDate;
    }

    public void setBeginDate(Date beginDate) {
        this.beginDate = beginDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    @Override
    public String toString() {
        return "Evection{" +
                "id=" + id +
                ", evectionName='" + evectionName + '\'' +
                ", num=" + num +
                ", beginDate=" + beginDate +
                ", endDate=" + endDate +
                ", destination='" + destination + '\'' +
                '}';
    }

    public Evection(Long id, String evectionName, Double num, Date beginDate, Date endDate, String destination) {
        this.id = id;
        this.evectionName = evectionName;
        this.num = num;
        this.beginDate = beginDate;
        this.endDate = endDate;
        this.destination = destination;
    }

    public Evection() {
    }
}

20.3、部署流程

/**
 * @author: yuqn
 * @Date: 2024/4/29 23:52
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RepositoryServoie
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、使用service进行流程部署,定义一个流程的名字,把bpmn和png部署到数据中
    Deployment deploy = repositoryService.createDeployment()
            .name("出差申请流程-variables")
            .addClasspathResource("bpmn/evection-global.bpmn20.xml")
            .deploy();
    // 4、输出部署信息
    System.out.println("流程部署id=" + deploy.getId());
    System.out.println("流程部署名字=" + deploy.getName());
}

20.4、启动流程

这里结合 uel 的方式。

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:03
 * @description:
 * 启动流程  启动的时候设置流程变量
 * 设置流程变量num
 * 设置任务负责人
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 流程定义的key
    String key = "evection-global";
    // 流程变量的map
    HashMap<String, Object> variables = new HashMap<>();
    // 设置流程变量
    Evection evection = new Evection();
    // 设置出差日期
    evection.setNum(3d);
    // 把流程变量的pojo放入map
    variables.put("evection",evection);
    // 设定任务负责人
    variables.put("assignee0","yuqn-lobal-0");
    variables.put("assignee1","yuqn-lobal-1");
    variables.put("assignee2","yuqn-lobal-2");
    variables.put("assignee3","yuqn-lobal-3");
    // 启动流程
    runtimeService.startProcessInstanceByKey(key,variables);
}

20.5、完成任务

原理:当完成部门经理审批yuqn-lobal-1后,如果pojo对象中的num值小于3,则下一个审核流程为财务审批yuqn-lobal-3;否则为 yuqn-lobal-2 -> yuqn-lobal-3。

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-global";
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务,
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-lobal-2")
            .singleResult();
    if(task != null){
        // 根据任务id,完成任务
        taskService.complete(task.getId());
    }
}

二十一、在完成任务的时候定义流程变量

该方法跟 步骤二十一 的区别在于: 步骤二十一是启动流程的时候就定义了变量,而这里是在完成某一个任务的时候,如果该任务后面有分支,那么完成该任务的时候就定义流程变量。

image.png

如上:在完成 创建出差申请 任务的时候不需要设置流程变量;而在完成 部门经理审批 任务的时候,就需要设置流程变量了;完成 部门经理审批 后,根据流程变量来判断下一步是走 总经理审批-> 财务审批 还是直接走 财务审批。

代码如下:

21.1、部署流程

/**
 * @author: yuqn
 * @Date: 2024/4/29 23:52
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RepositoryServoie
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、使用service进行流程部署,定义一个流程的名字,把bpmn和png部署到数据中
    Deployment deploy = repositoryService.createDeployment()
            .name("出差申请流程-variables-complete")
            .addClasspathResource("bpmn/evection-global.bpmn20.xml")
            .deploy();
    // 4、输出部署信息
    System.out.println("流程部署id=" + deploy.getId());
    System.out.println("流程部署名字=" + deploy.getName());
}

21.2、启动流程

这里将不再设置出差时间。

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:03
 * @description:
 * 启动流程  启动的时候设置流程变量
 * 设置流程变量num
 * 设置任务负责人
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 流程定义的key
    String key = "evection-global";
    // 流程变量的map
    HashMap<String, Object> variables = new HashMap<>();
    // 设定任务负责人
    variables.put("assignee0","yuqn-lobal-complete-0");
    variables.put("assignee1","yuqn-lobal-complete-1");
    variables.put("assignee2","yuqn-lobal-complete-2");
    variables.put("assignee3","yuqn-lobal-complete-3");
    // 启动流程
    runtimeService.startProcessInstanceByKey(key,variables);
}

21.3、完成任务

21.3.1、完成出差申请任务
/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-global";

    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-lobal-complete-0")
            .singleResult();
    if(task != null){
        // 根据任务id,完成任务,该方法用于没有流程变量的
        taskService.complete(task.getId());
       }
    }
21.3.2、完成经理审批任务
/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-global";

    // 设置流程变量,注:如果当前审批节点完成后,需要分支,则需要设置流程变量了
    Evection evection = new Evection();
    evection.setNum(2d);
    HashMap<String, Object> map = new HashMap<>();
    map.put("evection",evection);

    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-lobal-complete-1")
            .singleResult();
    if(task != null){
            // 根据任务id,完成任务,该方法用于有流程变量的
            taskService.complete(task.getId(),map);
        }
    }

二十二、使用组任务办理流程

原理:某个任务可能不止只有一个审批者,通过设置组,用于保存所有可以审批的工作人员信息。

22.1、创建流程图

image.png

image.png

image.png

image.png

image.png

22.2、组任务办理

image.png

22.3、部署任务

/**
 * @author: yuqn
 * @Date: 2024/4/29 23:52
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 1、创建processEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RepositoryServoie
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、使用service进行流程部署,定义一个流程的名字,把bpmn和png部署到数据中
    Deployment deploy = repositoryService.createDeployment()
            .name("出差申请流程-Candidate")
            .addClasspathResource("bpmn/evection-candidate.bpmn20.xml")
            .deploy();
    // 4、输出部署信息
    System.out.println("流程部署id=" + deploy.getId());
    System.out.println("流程部署名字=" + deploy.getName());
}

22.4、启动任务

/**
 * @author: yuqn
 * @Date: 2024/5/14 22:53
 * @description:
 * 启动流程
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 流程定义的key
    String key = "evection-candidate";
    // 启动流程
    runtimeService.startProcessInstanceByKey(key);
}

22.5、完成个人任务

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务,因为这里的组任务是设置在第二个审批任务,所以先把第一个审批任务完成
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-candidate";
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-candidate-0")
            .singleResult();
    if(task != null){
        // 根据任务id,完成任务
        taskService.complete(task.getId());
    }
}

22.6、组任务查询

/**
 * @author: yuqn
 * @Date: 2024/5/14 22:57
 * @description:
 * 查询组任务
 * @param: null
 * @return: null
 */
@Test
public void findGroupTaskList(){
    // 获取key
    String key = "evection-candidate";
    // 选择任务候选人,组里面的一个
    String candidateUser = "yuqn-candidate-1.0";
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskService
    TaskService taskService = processEngine.getTaskService();
    // 查询组任务
    List<Task> taskList = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskCandidateUser(candidateUser)
            .list();
    for (Task task : taskList) {
        System.out.println("-------------------------------");
        System.out.println("流程实例id = " + task.getProcessInstanceId());
        System.out.println("任务id = " + task.getId());
        System.out.println("任务负责人 = " + task.getAssignee());
    }
}

22.7、拾取任务

/**
 * @author: yuqn
 * @Date: 2024/5/14 23:44
 * @description:
 * 拾取任务,执行后,指定的人就能变为当前审批任务的负责人
 * @param: null
 * @return: null
 */
@Test
public void claimTask(){
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskService
    TaskService taskService = processEngine.getTaskService();
    // 当前任务id,为act_ru_task的id值
    String taskId = "162502";
    // 任务候选人
    String candidateUser = "yuqn-candidate-1.0";
    // 查询任务
    Task task = taskService.createTaskQuery()
            .taskId(taskId)
            .taskCandidateUser(candidateUser)
            .singleResult();
    if (task != null){
        // 拾取任务
        taskService.claim(taskId,candidateUser);
        System.out.println( "taskId-" + taskId + "- 用户 -" + candidateUser + " - 任务拾取完成");
    }
}

22.8、归还任务

/**
 * @author: yuqn
 * @Date: 2024/5/15 22:14
 * @description:
 * 任务归还
 * @param: null
 * @return: null
 */
@Test
public void testAssigneeToGroupTask(){
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 获取当前任务id
    String taskId = "162502";
    // 任务负责人
    String assignee = "yuqn-candidate-1.0";
    // 根据key和负责人查询任务
    Task task = taskService.createTaskQuery()
            .taskId(taskId)
            .taskAssignee(assignee)
            .singleResult();
    if(task!=null){
        // 归还任务,就是把负责人设置为空
        taskService.setAssignee(taskId,null);
        System.out.println("taskid-" + taskId + "-归还任务完成");
    }
}

22.9、交接任务

由原本的任务候选人改为另外一个。

/**
 * @author: yuqn
 * @Date: 2024/5/15 22:25
 * @description:
 * 任务交接,切换任务候选人
 * @param: null
 * @return: null
 */
@Test
public void testAssigneeToCandidateUser(){
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 当前任务id
    String taskId = "162502";
    // 任务负责人
    String assignee = "yuqn-candidate-1.0";
    // 任务候选人
    String candidateUser = "yuqn-candidate-1.1";
    // 根据key和负责人来查询任务
    Task task = taskService.createTaskQuery()
            .taskId(taskId)
            .taskAssignee(assignee)
            .singleResult();
    if(task!=null){
        // 交接,任务负责人由 yuqn-candidate-1.0 改为 yuqn-candidate-1.1
        taskService.setAssignee(taskId,candidateUser);
        System.out.println("taskid-" + taskId + "-交接任务完成");
    }
}

二十三、排他网关

使用排他网关,只选择其中1条或0条链路执行,情况如下:

1、满足多个条件,选择id最小的路径
2、都不满足,抛出异常(跟定义流程变量的主要区别)

原理如下:

image.png

启动流程后,开始逐步完成任务,最先开始填写出差申请,然后进行部门经理审核,此次后面有网关,所以完成该任务的前提是有‘定义流程变量’,当完成该任务后,根据流程变量确定下一步审批任务是总经理审批还是财务审批。

23.1、画流程图

image.png

image.png

image.png

image.png

image.png

image.png

image.png

23.2、部署程图

/**
 * @author: yuqn
 * @Date: 2024/5/16 18:01
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 创建processengine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取repositoryservice实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 使用repositoryservice部署
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("bpmn/evection-exclusive.bpmn20.xml")
            .name("出差申请流程-排他网关")
            .deploy();
    // 输出部署信息
    System.out.println("流程部署id" + deployment.getId());
    System.out.println("流程部署名称" + deployment.getName());
}

23.3、启动程图

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:03
 * @description:
 * 启动流程  启动的时候设置流程变量
 * 设置流程变量num
 * 设置任务负责人
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 流程定义的key
    String key = "evection-exclusive";
    // 流程变量的map
    HashMap<String, Object> variables = new HashMap<>();
    // 设置流程变量
    Evection evection = new Evection();
    // 设置出差日期
    evection.setNum(4d);
    // 把流程变量的pojo放入map
    variables.put("evection",evection);
    // 启动流程
    runtimeService.startProcessInstanceByKey(key,variables);
}

23.4、完成个人任务

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-exclusive";
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-exclusive-04")
            .singleResult();
    if(task != null){
        // 根据任务id,完成任务
        taskService.complete(task.getId());
    }
}

23.5、删除任务

/**
 * @author: yuqn
 * @Date: 2024/5/5 23:41
 * @description:
 * 删除流程部署信息
 * @param: null
 * @return: null
 * 当前流程如果没有全部完成,想要删除的话需要使用特殊方式,原理就是 级联删除
 */
@Test
public void deleteDeployMent(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 通过引擎来获取 RepositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 通过部署id删除流程部署信息
    String deploymentId = "172501";

    // 非级联删除
    //repositoryService.deleteDeployment(deploymentId);

    // 级联删除,流程没有完全完成也能删除
    repositoryService.deleteDeployment(deploymentId,true);
}

二十四、并行网关

使用并行网关,所有分支都会走一遍。如果有一个分支完成了,另一个分支还没完成,则需要等另外一个分支完成后,才后进入下一个任务。act_ru_task表会出现多条任务记录,只有全部完成,才能进入下一个任务。

24.1、画流程图

image.png

image.png

image.png

image.png

image.png

image.png

image.png

24.2、部署流程

/**
 * @author: yuqn
 * @Date: 2024/5/16 18:01
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 创建processengine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取repositoryservice实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 使用repositoryservice部署
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("bpmn/evection-parallel.bpmn20.xml")
            .name("出差申请流程-并行网关")
            .deploy();
    // 输出部署信息
    System.out.println("流程部署id" + deployment.getId());
    System.out.println("流程部署名称" + deployment.getName());
}

24.3、启动流程

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:03
 * @description:
 * 启动流程  启动的时候设置流程变量
 * 设置流程变量num
 * 设置任务负责人
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 流程定义的key
    String key = "evection-parallel";
    // 流程变量的map
    HashMap<String, Object> variables = new HashMap<>();
    // 设置流程变量
    Evection evection = new Evection();
    // 设置出差日期
    evection.setNum(4d);
    // 把流程变量的pojo放入map
    variables.put("evection",evection);
    // 启动流程
    runtimeService.startProcessInstanceByKey(key,variables);
}

24.4、完成任务

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-parallel";
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-parallel-03")
            .singleResult();
    if(task != null){
        // 根据任务id,完成任务
        taskService.complete(task.getId());
    }
}

二十五、包含网关

包含网关:满足条件的所有分支都执行后,才能进入下一个任务。不设置条件的分支默认为满足条件。

25.1、画流程图

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

25.2、部署程图

/**
 * @author: yuqn
 * @Date: 2024/5/16 18:01
 * @description:
 * 部署流程
 * @param: null
 * @return: null
 */
@Test
public void testDeployment(){
    // 创建processengine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取repositoryservice实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 使用repositoryservice部署
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("bpmn/evection-include.bpmn20.xml")
            .name("出差申请流程-包含网关")
            .deploy();
    // 输出部署信息
    System.out.println("流程部署id" + deployment.getId());
    System.out.println("流程部署名称" + deployment.getName());
}

25.3、启动程图

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:03
 * @description:
 * 启动流程  启动的时候设置流程变量
 * 设置流程变量num
 * 设置任务负责人
 * @param: null
 * @return: null
 */
@Test
public void testStartProcess(){
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取runtimeservice
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 流程定义的key
    String key = "evection-include";
    // 流程变量的map
    HashMap<String, Object> variables = new HashMap<>();
    // 设置流程变量
    Evection evection = new Evection();
    // 设置出差日期
    evection.setNum(4d);
    // 把流程变量的pojo放入map
    variables.put("evection",evection);
    // 启动流程
    runtimeService.startProcessInstanceByKey(key,variables);
}

25.4、完成任务

/**
 * @author: yuqn
 * @Date: 2024/5/12 1:04
 * @description:
 * 完成个人任务
 * @param: null
 * @return: null
 */
@Test
public void completTask(){
    // 定义流程key
    String key = "evection-include";
    // 获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取taskservice
    TaskService taskService = processEngine.getTaskService();
    // 完成任务
    Task task = taskService.createTaskQuery()
            .processDefinitionKey(key)
            .taskAssignee("yuqn-include-02-2")
            .singleResult();
    if(task != null){
        // 根据任务id,完成任务
        taskService.complete(task.getId());
    }
}

二十六、代码demo

github仓库地址: github.com/Yuqn/activi…