Bootstrap

Activiti审批流

名词解释

转办:某个节点,候选人是好几人。其中一个人拾取了该任务,发现不应该办理,可以转给候选人中的其他人

会签:

1 bpmn

StartEvent开始事件(重要)
EndEvent结束事件(重要)
IntermediateEvent中间事件
UserTask用户任务:表示需要人参与的任务,可以配置候选人/组/代理人等。(重要)
ServiceTask服务任务:调用外部服务或自动执行程序。
ManualTask手工任务:就是一个直接通过的任务。可以使用它来自动执行一些可以直接通过的任务
BusinessRuleTask规则任务:
SubProcess子流程:子流程表示多个activity的组合。子流程内部的元件禁止和外部的元件直连,只能作为一个整体与父流程的元件相连接。
Lane
ExclusiveGateway排他网关
EventGateway
IntermediateCatchingEvent
Annotation
ScriptTask脚本任务:用于执行定义好的脚本程序,流程执行到这个结点自动执行脚本。
MailTask        
ReceiveTask
   CallActivityTask    
Pool
ParallelGateway并行网关
InclusiveGateway包容性网关
   BoundaryEvent    
IntermediateThrowingEvent

BPMN2.0之顺序流和网关_Richard678的博客-CSDN博客_bpmn顺序

https://www.jianshu.com/p/6f38a0275e98/

userTask属性:

documentation文档
asynchronous异步
exclusive独家专用的
multi instance多实例
assignee代理人,受让人
candidate users候选人 ; 申请人
candidate groups候选组
due date到期日
form key表单键
priority优先事项
task listeners任务监听器
execution listeners执行监听器
form表单

2 Activiti表

表分类表名
一般数据
act_ge_bytearray通用的流程定义和流程资源
act_ge_property系统相关属性
流程历史记录
act_hi_actinst历史的流程实例 (节点表,审批到哪个节点了,)
act_hi_attachment历史的流程附件
act_hi_comment历史的流程说明性信息
act_hi_detail历史的流程运行中的细节信息
act_hi_identitylink历史的流程运行过程中用户关系
act_hi_procinst历史的流程实例
act_hi_taskinst历史的任务实例
act_hi_varinst历史的流程运行中的变量信息
流程定义表
act_re_deployment部署单元信息
act_re_model模型信息
act_re_procdef部署的流程定义
运行实例表
act_ru_deadletter_job死信
act_ru_event_subscr运行时事件
act_ru_execution运行时流程执行实例
act_ru_identitylink运行时用户关系信息,存储任务节点与参与者的相关信息
act_ru_integration集成
act_ru_job运行时作业
act_ru_suspended_job暂停
act_ru_task运行时任务
act_ru_timer_job
act_ru_variable运行时变量表
Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。
ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。
ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

activiti7和activiti6的区别:

不同点:activiti6是28张数据表,activiti7是25张,少了用户和组的三张表。相应的服务接口也少了俩:IdentityService和FormService。另外activiti7中对activiti6的API再次进行了封装,新增加了分布式和云部署的功能,核心没变

RepositoryService:流程定义和部署对象
RuntimeService:执行管理,包括流程实例和执行对象(正在执行)
TaskService:执行任务相关的(正在执行)
HistoryService:历史管理
IdentityService:Activiti表的用户角色组
ManagementService:引擎管理服务

 

 

 

activiti开发工作流的一个基本开发模式

功能复用:对于像查询待办任务、已办任务、抄送我的、我发起的流程、流程部署、流程挂起与激活、生成流程图等这样的可以复用的功能,使用一套代码即可,提供统一的接口或service。

功能不复用:但是对于启动流程、完成任务这样的功能,因为每个流程的参数或流程变量不一样,并且任务完成之后做的回调事情也不一样,如果不能复用,则每一个流程都单独开发这样的功能。
 

目前采用的方式是:对于启动流程、完成任务抽象出一个interface,让不同的流程service实现各自不同的操作;创建一个简单工厂,根据流程类型实例化不同的流程service;对外只暴露出启动流程和完成任务两个接口,前端传递不同的流程类型,执行不同的service操作。

数据表扩展:如果activiti提供的数据表无法满足业务需求,可以建立关联表,辅助业务运行。

3 开发准备

idea插件actiBPM 和pom

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
          <!--  <version>8.0.30</version>-->
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
      <!--  <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>6.0.0</version>
        </dependency>-->
<!--
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
        &lt;!&ndash; bpmn模型处理&ndash;&gt;
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-model</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
       &lt;!&ndash; bpmn转换&ndash;&gt;
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-converter</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
        &lt;!&ndash; bpmn json数据转换&ndash;&gt;
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-json-converter</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
        &lt;!&ndash; bpmn 布局&ndash;&gt;
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-bpmn-layout</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
        &lt;!&ndash; activiti 云支持&ndash;&gt;
        <dependency>
            <groupId>org.activiti.cloud</groupId>
            <artifactId>activiti-cloud-service-api</artifactId>
            <version>7.0.0.Betal</version>
        </dependency>
-->

    <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.6</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring-boot-starter</artifactId>
            <version>7.0.0.Beta2</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

 yml

server:
  port: 8080
spring:
  application:
    name: activiti
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/activiti?useUnicode=true&characterEncoding=UTF-8&useTimezone=true&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true
    username: root
    password: root
    druid:
      filter:
        stat:
          enabled: true
          db-type: mysql
          log-slow-sql: true

  activiti:
    #    false:默认值。在activiti启动时,会对比数据库表中保存的版本,如果没有表或版本不匹配,将抛出异常。(生产环境常用)
    #    true:activiti会对数据库中所有表进行更新操作。如果表不存在,将会创建。(开发环境常用)
    #    create-drop:在activiti启动时创建表,在关闭时删除表,必须手动关闭引擎才会删除表。(单元测试用)
    #    drop-create:在activiti启动时删除旧表,然后创建新表,不需要关闭引擎。
    database-schema-update: true
    #检测历史表是否存在,activiti7默认没有开启数据库历史记录,true启动数据库历史记录
    db-history-used: true
      #记录历史等级,可配置的历史级别有:none,activity,audit,full
      # none:不保存任何的历史数据,因此在流程执行过程中,这是最高效的
      # activity:级别高于none,保存流程实例与流程行为,其他数据不保存
    # audit:除保存activity保存的数据外,还会保存全部的流程任务及其属性。history-level的默认值
    # full:保存历史数据的最高级别,会额外保存全部流程相关的细节数据。
    history-level: full
    #校验流程文件,默认校验resources下的process文件夹的流程文件
    check-process-definitions: false
logging:
  pattern:
    console: "%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n"
  level:
    org.activiti.engine.impl.persistence.entity: trace
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

资源文件下加配置文件activiti.cfg.xml和log4j.properties文件

 activiti.cfg.xml:springboot方式就不用了。

<?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">
 
 
    <!--dbcp数据源-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/activiti"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
 
    <!--配置Activiti的ProcessEngineConfiguration对象,因为没有跟spring整合,所以这里使用单例的。-->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--指定数据表生成策略,该策略是,若数据表不存在则创建,存在则更新-->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>

代码实战

Activiti学习——踩坑和经验_chuchui5713的博客-CSDN博客

分配个人任务的三种方式
1:直接给值,在Xxxx.bpmn文件中指定
2:流程变量${流程变量的名称}或者#{}
3:使用类 监听这个类(实现一个接口),指定任务的办理人(setAssgnee())

个人任务和组任务的查询一样吗?
* 不一样
* 都是用TaskService完成(TaskService.createTasQuery)
* 个人任务(taskAssgnee),组任务(taskCandidateUser)
* 数据库存放,个人任务(类型:参与),组任务(类型,参与,候选)
 

bpmn创建一个简单请假流程

张三提交申请单---> 李四经理审批--->王五总经理审批

生成图片流程:

 1将travel.bpmn 改名为 travel.xml

2:右击 找到Diagrams --->show BPMN 2.0 Designer

3: 点击导出 image

4 将 travel.xml改为 travel.bpmn

 

结论:

  act_re_deployment (流程部署 )和act_re_procdef(流程定义) 一对多的关系

   procdef表中,可以有多条记录,每一条记录,对应一个流程的定义信息。

   张三 走这个出差申请流程

   李四 也走这个出差申请流程

简单的案例代码

package com.example.activiti;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;

@SpringBootTest
class ActivitiApplicationTests {
    static ProcessEngine processEngine = null;

    @BeforeEach
    void test() {
        /**
         * 初始化流程引擎对象,将会根据配置创建25数据表(创建了索引和外键)
         */
        processEngine = ProcessEngines.getDefaultProcessEngine();

    }

    /**
     * 部署流程  将流程保存到数据中
     */
    @Test
    void test1() {
        RepositoryService repositoryService = processEngine.getRepositoryService();

        //zip方式部署 (可以很多流程都压缩在一个zip下)
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/travel.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        Deployment deploy = repositoryService.createDeployment().addZipInputStream(zipInputStream)
               // .name("")
                .deploy();

        // 单个部署方式
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/travel.bpmn")
                .addClasspathResource("bpmn/travel.png")
              //  .name("请假流程测试")
              //  .category("办公类别") //设置部署的类别
                .deploy();
        System.out.println(deployment.getId());//流程部署id  6f2030ef-58ec-11ed-bbe8-fa89d281dc2b
        System.out.println(deployment.getName());//流程部署名字  请假流程测试
        System.out.println(deployment.getKey());//null
        System.out.println(deployment.getCategory());//null
        System.out.println(deployment.getDeploymentTime());
        System.out.println(deployment.getTenantId());//null

     /*
         受影响的表:3个
         act_re_deployment:流程部署表 : 添加一条流程部署记录  主键是贯穿这三个表
         act_re_procdef::流程定义:添加一条流程定义记录,一个流程定义记录和一个流程图一一对应,流程定义记录的key就是流程图的id
         act_ge_bytearray:blob形式保存部署的资源
         */

        /*
        流程部署意味着两件事:
        1、将流程定义文件放到activiti引擎配置的持久化存储中,以便activiti引擎重启时能再次读取部署的流程。
        2、解析bpmn文件并转化为activiti内存中的对象模型,然后就能使用acticiti提供的api对持久化的数据进行操作。
         */
    }

    /**
     * 查询流程定义 act_re_procdef
     */
    @Test
    void tes2() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> myTravel_1 = processDefinitionQuery.processDefinitionKey("myTravel_1")
                .orderByProcessDefinitionVersion() //根据 Version 正序
                .asc() //正序
                .list();
        for (ProcessDefinition processDefinition : myTravel_1) {
            System.out.println("流程定义ID: "+processDefinition.getId());//IDmyTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b
            System.out.println("流程定义名称: "+processDefinition.getName()); //出差申请流程
            System.out.println("流程定义key: "+processDefinition.getKey()); //keymyTravel_1
            System.out.println("流程定义版本: "+processDefinition.getVersion()); //1
            System.out.println("流程定义部署id: "+processDefinition.getDeploymentId()); //710668f8-5904-11ed-b08d-fa89d281dc2b
        }
    }

    /**
     * 删除流程定义 act_re_procdef
     */
    @Test
    void tes3() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //通过部署id删除流程部署信息 不会删除历史表的信息
        repositoryService.deleteDeployment("54215d66-5903-11ed-a890-fa89d281dc2b");
        //历史信息也会删除
        repositoryService.deleteDeployment("54215d66-5903-11ed-a890-fa89d281dc2b",true);
        /**
         * delete from ACT_GE_BYTEARRAY where DEPLOYMENT_ID_ =
         * delete from ACT_RE_DEPLOYMENT where ID_ =
         * delete from ACT_RE_PROCDEF where DEPLOYMENT_ID_ =
         *  delete from ACT_RU_IDENTITYLINK where PROC_DEF_ID_ =
          */
    }

    /**
     * 下载流程
     */
    @Test
    void tes4() throws IOException {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //查询流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myTravel_1").singleResult();
        //获取流程部署id
        String deploymentId = processDefinition.getDeploymentId();

        //获取图片目录和名字
        String pngName = processDefinition.getDiagramResourceName();
        InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);

        //获取bpmn目录和名字
        String bpmnName = processDefinition.getResourceName();
        InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);
        File pngfile = new File("D:/travel.png");
        File bpmnfile = new File("D:/travel.bpmn");

        FileOutputStream pngOutputStream = new FileOutputStream(pngfile);
        FileOutputStream bpmnOutputStream = new FileOutputStream(bpmnfile);

        IOUtils.copy(pngInput, pngOutputStream);
        IOUtils.copy(bpmnInput, bpmnOutputStream);
        pngInput.close();
        bpmnInput.close();
        pngOutputStream.close();
        bpmnOutputStream.close();
    }



    /**
     * 运行工作流
     */
    @Test
    void test5() {
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //act_re_procdef---拿来的参数
        ProcessInstance processInstance = runtimeService.startProcessInstanceById("myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b");
        //  runtimeService.startProcessInstanceByKey("myTravel_1");
        System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b
        System.out.println("流程实例ID"+processInstance.getId());//c96e78ef-58f7-11ed-9f8b-fa89d281dc2b
        System.out.println("流程活动ID"+processInstance.getActivityId());//null

      /*  act_ru_task 任务信息
      *   act_ru_identitylink 标识链接   流程的参与用户信息
      *   act_ru_execution 处决    流程正在执行信息
      *   act_hi_taskinst  任务    流程任务历史信息
      *   act_hi_procinst           流程实例历史信息
      *   act_hi_identitylink     流程的参与用户信息历史
      *   act_hi_actinst          流程实例执行历史
       *
      * */
    }

    /**
     * 查询张三正在执行任务查询
     *   正在执行的任务会在这个表 ACT_RU_TASK ,一旦这个节点完成,会到历史表中,下一个节点到  ACT_RU_TASK 中
     *  https://blog.csdn.net/JHC23/article/details/97001687?ops_request_misc=&request_id=&biz_id=102&utm_term=activi&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-5-97001687.142^v62^pc_search_tree,201^v3^control_1,213^v1^control&spm=1018.2226.3001.4187
     */
    @Test
    void test6() {
        TaskService taskService = processEngine.getTaskService();
        //创建任务查询对象
        TaskQuery taskQuery = taskService.createTaskQuery();
        //查看办理人的任务列表
        List<Task> list = taskQuery
                 .processDefinitionKey("myTravel_1") // 流程key
                 .taskAssignee("张三").list();//要查询的负责人
        //select distinct RES.* from ACT_RU_TASK RES WHERE RES.ASSIGNEE_ ="张三"
       // select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = '张三' and D.KEY_ = 'myTravel_1'
        for (Task task : list) {
            System.out.println("任务办理人:"+task.getAssignee());
            System.out.println("任务id:" + task.getId());
            System.out.println("任务名称:"+ task.getName());
            System.out.println("流程实例id:"+ task.getProcessInstanceId());

        }

    }

    /**
     * 张三提交申请单 完成个人任务
     */
    @Test
    void test7() {

        TaskService taskService = processEngine.getTaskService();
        //根据任务id act_ru_task 表的 id 完成任务
       //  act_ru_task 目前节点是 提交申请单
        taskService.complete("75b2666e-598d-11ed-951f-fa89d281dc2b");

      // 执行后 act_ru_task 节点变成 经理审批    act_hi_taskinst 也会多一个经理审批
       /*流程sql
         select * from ACT_RU_TASK where ID_ = 'c972e5c3-58f7-11ed-9f8b-fa89d281dc2b'
       * select * from ACT_RE_PROCDEF where ID_ = 'myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b'
       * select * from ACT_RE_DEPLOYMENT where ID_ ='6f2030ef-58ec-11ed-bbe8-fa89d281dc2b'
       * select * from ACT_GE_BYTEARRAY where DEPLOYMENT_ID_ = '6f2030ef-58ec-11ed-bbe8-fa89d281dc2b' order by NAME_ asc
       *  insert into ACT_HI_TASKINST 经理审批的数据
       *  insert into ACT_HI_ACTINST  经理审批的数据
       *  insert into ACT_HI_IDENTITYLINK  李四人员数据
          insert into ACT_RU_TASK     经理审批的数据
          insert into ACT_RU_IDENTITYLINK 李四人员数据
       *  update ACT_HI_ACTINST       张三
          update ACT_RU_EXECUTION   update ACT_HI_TASKINST   delete from ACT_RU_TASK 张三
       */

    }


    /**
     * 查看历史信息 (审批节点)  ACT_HI_ACTINST
     */
    @Test
    void test8() {
        HistoryService historyService = processEngine.getHistoryService();
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
        //act_hi_actinst表   PROC_INST_ID_字段
        //select RES.* from ACT_HI_ACTINST RES WHERE RES.PROC_INST_ID_ = ?
        instanceQuery.processInstanceId("c96e78ef-58f7-11ed-9f8b-fa89d281dc2b");
        //排序 开始
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
        List<HistoricActivityInstance> list = instanceQuery.list();
        for (HistoricActivityInstance instance : list) {
            System.out.println(instance.getActivityId());//_3
            System.out.println(instance.getActivityName());// 经理审批
            System.out.println(instance.getProcessDefinitionId()); //myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b
            System.out.println(instance.getProcessInstanceId());//c96e78ef-58f7-11ed-9f8b-fa89d281dc2b
        }

    }



    @Test
    void del() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
       // repositoryService.deleteDeployment();


        RuntimeService runtimeService = processEngine.getRuntimeService();
        //act_re_procdef---拿来的参数
     //   ProcessInstance processInstance = runtimeService.startProcessInstanceById("myTravel_1:1:6f3602e2-58ec-11ed-bbe8-fa89d281dc2b");
        runtimeService.deleteProcessInstance("51b423d0-5902-11ed-b595-fa89d281dc2b","");
    }







}

晋级版

绑定其他业务表

  占位符方式

UEL-value方式:    ${submitName}  

UEL-method方式: ${User.submitName}

结合版: ${userService.findUser(userBean)}

   详解:userService是spring容器的类,调用接口 findUser 入参 userBean 是activiti流程变量

其他:${order.price>100 && order.price<200}  表达式支持解析基础类型,bean,list,array,map

    static ProcessEngine processEngine = null;

    @BeforeEach
    void test() {
        /**
         * 初始化流程引擎对象,将会根据配置创建25数据表(创建了索引和外键)
         */
        processEngine = ProcessEngines.getDefaultProcessEngine();

    }  
  /**
     * 分配任务负责人
     * 1:固定方式
     * 2 uel表达式方式 ( UEL-value 和 UEL-method)
     * 3 监听器方式
     */
    @Test
    void test4() {
      // 1:固定方式 就是我们用idea软件画图的时候直接给死了人员名称。创建申请单就是张三。

     /*  注意一定变成xml方式看看是不是写的表达式,有的时候变不过来
       2: UEL-value方式: ${submitName}
       UEL-method方式: ${User.submitName}
       结合版: ${userService.findUser(userBean)}  userService是spring容器的类,调用接口 findUser 入参 userBean 是activiti流程变量
       其他:${order.price>100 && order.price<200}  表达式支持解析基础类型,bean,list,array,map
       */
       RepositoryService repositoryService = processEngine.getRepositoryService();
         Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/travel3.bpmn")
                 .name("动态人员出差申请流程")
                .deploy();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("submitName","张三-动态");
        hashMap.put("approval1","李四-动态");
        hashMap.put("approval2","王五-动态");
        runtimeService.startProcessInstanceByKey("myTravel_3",hashMap);
        // act_ru_variable 会存 字段和人名 映射关系

     // 删除   repositoryService.deleteDeployment("240b39a6-59c8-11ed-8bd7-fa89d281dc2b",true);
    }

 挂起

 /**
     * 挂起:当流程实例没有跑完,如果已经挂起,就不能继续处理了,只有当流程激活后,才能继续执行。
     * 挂起后 完成任务 taskService.complete() 报错会
     * act_ru_task:SUSPENSION_STATE_  暂停_状态_  1 未暂停  2 暂停
     */
    @Test
    void test3() {
        /**
         * 多实例流程的挂起
          */
        RepositoryService repositoryService = processEngine.getRepositoryService();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myTravel_1").singleResult();
        //当前所有流程实例是否被挂起
        boolean suspended = processDefinition.isSuspended();
         if(suspended){
             //激活方法 参数1:流程定义id 参数2:是否激活  参数3:激活时间
             repositoryService.activateProcessDefinitionById(processDefinition.getId(),true,null);
         }else {
           //挂起方法  参数1:流程定义id 参数2:是否暂停  参数3:暂停时间
             repositoryService.suspendProcessDefinitionById(processDefinition.getId(),true,null);
         }

        /**
         * 单个流程实例的挂起
         */
        RuntimeService runtimeService = processEngine.getRuntimeService();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processDefinitionId("c96e78ef-58f7-11ed-9f8b-fa89d281dc2b").singleResult();
        boolean suspended1 = processInstance.isSuspended();
        if(suspended1){
            //激活方法 参数1:流程定义id
            runtimeService.activateProcessInstanceById(processInstance.getId());
        }else {
            //挂起方法
            runtimeService.suspendProcessInstanceById(processInstance.getId());
        }

    }

监听器方式 动态分配人员 我的插件不好使了。始终出不来 算了

 使用global变量控制流程

 员工创建出差申请单,由经理审核,经理审核通过后出差3天一下直接由财务审批,3天以上由总经理审批,在财务审核。

 

   static ProcessEngine processEngine = null;

    @BeforeEach
    void test() {
        /**
         * 初始化流程引擎对象,将会根据配置创建25数据表(创建了索引和外键)
         */
        processEngine = ProcessEngines.getDefaultProcessEngine();

    }
/**
     * 使用global变量控制流程
     */
    @Test
    void test6() {
        //保存到数据库
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/evection-global.bpmn")
                .name("global变量动态人员出差申请流程")
                .deploy();
       //开启流程
        RuntimeService runtimeService = processEngine.getRuntimeService();
        HashMap<String, Object> hashMap = new HashMap<>();
        Evection evection = new Evection();
        evection.setNum(2.0);
        evection.setId(1L);
        evection.setReason("项目出差原因");
        hashMap.put("evection",evection);
        hashMap.put("submitName","张三提交");
        hashMap.put("approval1","李四经理审批");
        hashMap.put("approval2","王五总经理-动态");
        hashMap.put("approval3","李六财务-动态");
        runtimeService.startProcessInstanceByKey("evection-global",hashMap);
    }

组任务

就是给当前流程设置多个负责人。

 

多人审批该任务时候。不能立即审批。先看这个人是不是候选人之一,是的话,还要在拾取该任务,变成个人任务。才能办理。

如果不想办理,还要将任务还回去。

 /**
     * 组任务 74
     */
    @Test
    void test7() {
        //保存到数据库
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/travel-candidate.bpmn")
                .name("组人员出差申请流程")
                .deploy();
        //流程定义的key
        String key="travel-candidate";
        //开启流程
        RuntimeService runtimeService = processEngine.getRuntimeService();
        runtimeService.startProcessInstanceByKey(key);
        TaskService taskService = processEngine.getTaskService();

        //创建申请单(张三) ----->经理审批(候选人  wangwu和lisi)-------等等
        String userId="张三";
        //创建申请单步骤
        // 张三查询自己待办任务
        Task task1 = taskService.createTaskQuery().processDefinitionKey(key).taskAssignee(userId).singleResult();
        if(task1!=null){
            //完成任务
            taskService.complete(task1.getId());
        }

        //经理审批  (组任务模式  候选人  wangwu和lisi)
        String candidateUserId="wangwu";
        //查询这个候选人待办任务
        Task task3 = taskService.createTaskQuery().processDefinitionKey(key)
                .taskCandidateUser(candidateUserId) //候选人
                //.list()  查询所有待办
                  .singleResult();
        System.out.println("任务id"+task3.getId());
        System.out.println("任务负责人"+task3.getAssignee()); //null 因为还没有人拾取任务
        if(task3!=null){
            //拾取该任务
            taskService.claim(task3.getId(),candidateUserId);
        }
        //拾取完可以办理或归还任务
       // taskService.complete(task3.getId()); 完成任务

        //归还任务
        taskService.setAssignee(task3.getId(),null); //归还任务就是把负责人设置为null

        // 任务的转办(任务交接) :这个任务我做不了,想交给别人做。
        // 候选人王五做不了,转给李四做
        taskService.setAssignee(task3.getId(),"lisi"); //转办任务就是把负责人设置为目标人
    }

网关

排他网关

 排他网关exclusiveGateway: 排他网关只会选择一个为true去执行。都为true 选择id值较小的那条线去执行。
  (global变量控制流程)连线上设置分支条件方式:  不符合任何一条条件时,会结束任务
  排他网关方式:                              不符合任何一条条件时,会抛异常。扔我们知道哪出问题了。

并行网关

拆分:拆分处,有几个分支就会走几个分支,不会因为连线处有条件而不执行。

聚合:等所有分支都执行完,才能继续往下走。

 

 

;