工作流实战之Activiti7

楔子

本文主要介绍了 Activiti 的相关使用与集成,适合想要学习 Activiti 的读者食用。

Activiti 介绍

Activiti 是目前使用最为广泛的开源工作流引擎之一,在小七 2017 年走向程序员这一条不归路的时候,它就已经是开源工作流引擎的老大哥了。

Activiti 官网

学习一门新技术/新框架,我们第一件事就是从它的官网入手,下面贴出 Activiti 的官网

Open Source Business Automation | Activiti

在这里插入图片描述

从官网的描述,我们可以知道 Activiti 是领先的轻量级的、以 java 为中心的开源 BPMN 引擎,可以支持现实世界的流程自动化需求。 Activiti Cloud 是新一代的业务自动化平台,提供了一组旨在在分布式基础架构上运行的云原生构建块。

BPMN 建模语言

官网既然提到了 BPMN,那么首先我们必须要知道什么是 BPM。BPM 即 Business Process Managemenet,业务流程管理。是一种规范化的构造端到端的业务流程,以持续的提高组织业务效率。在常见的商业管理教育如 EMBA、MBA 中都包含了 BPM 的课程。 说人话就是,比如你请假,需要向你老板提交一个申请,你老板批准后,你才能休假,这就是一个请假流程。

而 BPMN 是 Business Process Model And Notation 业务流程模型和符号,用来描述业务流程的一种建模标准。说人话,就是“书同文,车同轨”,大家用统一的符号,来描述我们的各个业务流程,比如说请假流程,就可以抽象如下如所示:
在这里插入图片描述

这里贴出常用的图形所代表的意义,让各位读者先混个眼熟。
在这里插入图片描述

Activiti 使用步骤

新建一个 Maven 项目,项目目录结构如下:
在这里插入图片描述

引入依赖

在最外层 pom 中统一定义依赖

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <slf4j.version>1.6.6</slf4j.version>
    <log4j.version>1.2.12</log4j.version>
    <activiti.version>7.1.0.M6</activiti.version>
    <activiti.cloud.version>7.0.0.Beta1</activiti.cloud.version>
    <mysql.version>8.0.20</mysql.version>
    <java.version>1.8</java.version>
    <slf4j.version>1.6.6</slf4j.version>
    <log4j.version>1.2.12</log4j.version>
    <mybatis.version>3.4.5</mybatis.version>
    <junit.version>4.12</junit.version>
    <commonsio.version>2.6</commonsio.version>
    <dbcp.version>1.4</dbcp.version>
</properties>

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在 BaseActivitiDemo 项目下的 pom 中引入依赖

<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>
    <!-- mysql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!-- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <!-- 链接池 -->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>${dbcp.version}</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>${commonsio.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</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>

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

添加配置

日志配置

在 BaseActivitiDemo 项目的 resource 下新建 log4j.properties 文件,并添加配置

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=D:\activiti7.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n

   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Activiti 配置

在 BaseActivitiDemo 项目的 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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contex
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<span class="token comment">&lt;!-- 这里可以使用 链接池 dbcp--&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>bean</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dataSource<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>org.apache.commons.dbcp.BasicDataSource<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>driverClassName<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.mysql.cj.jdbc.Driver<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>url<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>jdbc:mysql://localhost:3306/activiti?serverTimezone=GMT%2B8<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>username<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>root<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>password<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>123456<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>maxActive<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>3<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>maxIdle<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>bean</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>bean</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>processEngineConfiguration<span class="token punctuation">"</span></span>
      <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- 引用数据源 上面已经设置好了--&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dataSource<span class="token punctuation">"</span></span> <span class="token attr-name">ref</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>dataSource<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token comment">&lt;!-- activiti 数据库表处理策略 --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>property</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>databaseSchemaUpdate<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>bean</span><span class="token punctuation">&gt;</span></span>

</beans>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

初始化数据库表

新建数据库 activiti

在这里插入图片描述

新建单元测试类 TestCreateTable

在这里插入图片描述

内容如下:

public class TestCreateTable {
    /**
     * 生成 activiti 的数据库表
     */
    @Test
    public void testCreateDbTableByDefault() {
        // 默认创建方式
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        System.out.println(processEngine);
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

执行测试代码后,控制台会打印许多 sql 语句,再次观察 activiti 数据库,我们会发现多了 25 张表。
在这里插入图片描述

加餐

我们没有指定配置文件,程序是怎么创建这些表的呢?

我们跟进 getDefaultProcessEngine 方法可以发现,它其实是个包装方法,内部调用的是 getProcessEngine(string)。

public static ProcessEngine getDefaultProcessEngine() {
  return getProcessEngine(NAME_DEFAULT);
}

 
 
  • 1
  • 2
  • 3

继续看 getProcessEngine(string),因为我们现在并没有初始化,所以会调用 init()方法。

public static ProcessEngine getProcessEngine(String processEngineName) {
  if (!isInitialized()) {
    init();
  }
  return processEngines.get(processEngineName);
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

从 init()方法中圈红的地方我们可以知道,框架默认会去读取 classpath:下的 activiti.cfg.xml 和 activiti-context.xml 两个配置文件的。

表结构解析

总览

让我们再来看一下这25张表
在这里插入图片描述

虽然表很多,但是仔细观察,我们会发现Activiti 使用到的表都是 ACT_ 开头的。表名的第二部分用两个字母表明表的用途。

  • ACT_RE :'RE’表示 repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
  • ACT_RU:'RU’表示 runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。Activiti 只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。保证了框架的运行速度。
  • ACT_HI:'HI’表示 history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
  • ACT_GE : GE 表示 general。 通用数据及其设置,全局适用。
详解
用途归类表名解释
全局通用数据表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
存放运行时流程变量
其他act_evt_log
存放事件日志
act_procdef_info
存放流程定义的动态变更信息

核心类解析

类名解释
RepositoryService
是activiti的资源管理类,提供了管理和控制流程发布包和流程定义的操作。
RuntimeService
Activiti的流程运行管理类。可以从这个类中获取流程执行的信息
TaskService
Activiti的任务管理类。可以从这个类中获取任务的信息。
HistoryService
Activiti的历史管理类,可以查询历史信息。
ManagerService
Activiti的引擎管理类,提供了对 Activiti 流程引擎的管理和维护功能。

安装插件

这里主要讲idea的插件,直接在Plugins中搜索Activiti BPMN visualizer和JBoss jBPM,安装即可。

注:actiBPM在idea里的使用体验实在不好,这里就不推荐大家安装了。
在这里插入图片描述

常用API介绍

定制流程

首先我们定义一个简单的请假流程。

在resources下新建Leave.bpmn20.xml文件
在这里插入图片描述

右键选择view bpmn(Activiti) Diagram
在这里插入图片描述

可以看到以下界面
在这里插入图片描述

在红框中点击右键,开始画图,这里我们先选择一个开始事件
在这里插入图片描述

选择一个user task
在这里插入图片描述

选择user task方框填入以下属性
在这里插入图片描述

再创建一个user task,并填入以下属性
在这里插入图片描述

再创建一个user task,并填入以下属性
在这里插入图片描述

选择结束事件
在这里插入图片描述

最后我们得到了这样一个流程图

在这里插入图片描述

同时我们可以看到,左侧的xml文件发生了变化
在这里插入图片描述

部署流程

接下来新建测试类ActivitiDemo并添加以下内容

/**
 * 部署流程定义
 */
@Test
public void testDeployment() {
    // 1、创建ProcessEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、得到RepositoryService实例
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、使用RepositoryService进行部署
    Deployment deployment = repositoryService.createDeployment()
            // 添加bpmn资源
            .addClasspathResource("bpmn/Leave.bpmn20.xml")
            // 添加png资源
            .addClasspathResource("bpmn/Leave.png")
            .name("请假申请流程")
            .deploy();
    System.out.println("流程部署id:" + deployment.getId());
    System.out.println("流程部署名称:" + deployment.getName());
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

运行测试方法后,我们可以看到控制台打印了一些sql,整个部署过程操作了三张数据表:
act_ge_bytearray 流程资源表 ,每个流程定义对应两个资源记录,bpmn和png。
在这里插入图片描述

act_re_deployment 流程定义部署表,每部署一次增加一条记录 。

在这里插入图片描述

act_re_procdef 流程定义表,部署每个新的流程定义都会在这张表中增加一条记录。
在这里插入图片描述

启动实例

接下来我们启动流程实例

/**
 * 启动流程实例
 */
@Test
public void testStartProcess() {
    // 1、创建ProcessEngine
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RunTimeService
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 3、根据流程定义Id启动流程
    ProcessInstance processInstance = runtimeService
            .startProcessInstanceByKey("Leave");
    System.out.println("流程定义id:" + processInstance.getProcessDefinitionId());
    System.out.println("流程实例id:" + processInstance.getId());
    System.out.println("当前活动Id:" + processInstance.getActivityId());
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

同样我们观察控制台日志,发现涉及插入语句的的表如下

2022-08-15 21:45:39,919 1252  [           main] DEBUG ti.engine.impl.db.DbSqlSession  - inserting: org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntityImpl@3174cb09
2022-08-15 21:45:39,919 1252  [           main] DEBUG mpl.insertHistoricTaskInstance  - ==>  Preparing: insert into ACT_HI_TASKINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, PARENT_TASK_ID_, DESCRIPTION_, OWNER_, ASSIGNEE_, START_TIME_, CLAIM_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TASK_DEF_KEY_, FORM_KEY_, PRIORITY_, DUE_DATE_, CATEGORY_, TENANT_ID_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) 
2022-08-15 21:45:39,921 1254  [           main] DEBUG mpl.insertHistoricTaskInstance  - ==> Parameters: 2505(String), Leave:1:4(String), 2501(String), 2502(String), 创建出差申请(String), null, 创建出差申请(String), null, employee(String), 2022-08-15 21:45:39.918(Timestamp), null, null, null, null, sid-d0797050-fe53-4ff7-8506-855ba3059d8d(String), null, 50(Integer), null, null, (String)
2022-08-15 21:45:39,922 1255  [           main] DEBUG mpl.insertHistoricTaskInstance  - <==    Updates: 1
2022-08-15 21:45:39,922 1255  [           main] DEBUG ti.engine.impl.db.DbSqlSession  - inserting: HistoricProcessInstanceEntity[superProcessInstanceId=null]
2022-08-15 21:45:39,922 1255  [           main] DEBUG .insertHistoricProcessInstance  - ==>  Preparing: insert into ACT_HI_PROCINST ( ID_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, START_TIME_, END_TIME_, DURATION_, START_USER_ID_, START_ACT_ID_, END_ACT_ID_, SUPER_PROCESS_INSTANCE_ID_, DELETE_REASON_, TENANT_ID_, NAME_ ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) 
2022-08-15 21:45:39,922 1255  [           main] DEBUG .insertHistoricProcessInstance  - ==> Parameters: 2501(String), 2501(String), null, Leave:1:4(String), 2022-08-15 21:45:39.893(Timestamp), null, null, null, sid-0302a100-d63d-4daa-8e3a-fbce9d28485a(String), null, null, null, (String), null
2022-08-15 21:45:39,923 1256  [           main] DEBUG .insertHistoricProcessInstance  - <==    Updates: 1
2022-08-15 21:45:39,934 1267  [           main] DEBUG InsertHistoricActivityInstance  - ==>  Preparing: insert into ACT_HI_ACTINST ( ID_, PROC_DEF_ID_, PROC_INST_ID_, EXECUTION_ID_, ACT_ID_, TASK_ID_, CALL_PROC_INST_ID_, ACT_NAME_, ACT_TYPE_, ASSIGNEE_, START_TIME_, END_TIME_, DURATION_, DELETE_REASON_, TENANT_ID_ ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
2022-08-15 21:45:39,935 1268  [           main] DEBUG InsertHistoricActivityInstance  - ==> Parameters: 2503(String), Leave:1:4(String), 2501(String), 2502(String), sid-0302a100-d63d-4daa-8e3a-fbce9d28485a(String), null, null, null, startEvent(String), null, 2022-08-15 21:45:39.909(Timestamp), 2022-08-15 21:45:39.91(Timestamp), 1(Long), null, (String), 2504(String), Leave:1:4(String), 2501(String), 2502(String), sid-d0797050-fe53-4ff7-8506-855ba3059d8d(String), 2505(String), null, 创建出差申请(String), userTask(String), employee(String), 2022-08-15 21:45:39.911(Timestamp), null, null, null, (String)
2022-08-15 21:45:39,936 1269  [           main] DEBUG InsertHistoricActivityInstance  - <==    Updates: 2
2022-08-15 21:45:39,936 1269  [           main] DEBUG ti.engine.impl.db.DbSqlSession  - inserting: org.activiti.engine.impl.persistence.entity.HistoricIdentityLinkEntityImpl@4d411036
2022-08-15 21:45:39,936 1269  [           main] DEBUG mpl.insertHistoricIdentityLink  - ==>  Preparing: insert into ACT_HI_IDENTITYLINK (ID_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_) values (?, ?, ?, ?, ?, ?) 
2022-08-15 21:45:39,936 1269  [           main] DEBUG mpl.insertHistoricIdentityLink  - ==> Parameters: 2506(String), participant(String), employee(String), null, null, 2501(String)
2022-08-15 21:45:39,937 1270  [           main] DEBUG mpl.insertHistoricIdentityLink  - <==    Updates: 1
2022-08-15 21:45:39,938 1271  [           main] DEBUG EntityImpl.bulkInsertExecution  - ==>  Preparing: insert into ACT_RU_EXECUTION (ID_, REV_, PROC_INST_ID_, BUSINESS_KEY_, PROC_DEF_ID_, ACT_ID_, IS_ACTIVE_, IS_CONCURRENT_, IS_SCOPE_,IS_EVENT_SCOPE_, IS_MI_ROOT_, PARENT_ID_, SUPER_EXEC_, ROOT_PROC_INST_ID_, SUSPENSION_STATE_, TENANT_ID_, NAME_, START_TIME_, START_USER_ID_, IS_COUNT_ENABLED_, EVT_SUBSCR_COUNT_, TASK_COUNT_, JOB_COUNT_, TIMER_JOB_COUNT_, SUSP_JOB_COUNT_, DEADLETTER_JOB_COUNT_, VAR_COUNT_, ID_LINK_COUNT_, APP_VERSION_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
2022-08-15 21:45:39,939 1272  [           main] DEBUG EntityImpl.bulkInsertExecution  - ==> Parameters: 2501(String), 2501(String), null, Leave:1:4(String), null, true(Boolean), false(Boolean), true(Boolean), false(Boolean), false(Boolean), null, null, 2501(String), 1(Integer), (String), null, 2022-08-15 21:45:39.893(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), null, 2502(String), 2501(String), null, Leave:1:4(String), sid-d0797050-fe53-4ff7-8506-855ba3059d8d(String), true(Boolean), false(Boolean), false(Boolean), false(Boolean), false(Boolean), 2501(String), null, 2501(String), 1(Integer), (String), null, 2022-08-15 21:45:39.908(Timestamp), null, false(Boolean), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), 0(Integer), null
2022-08-15 21:45:39,940 1273  [           main] DEBUG EntityImpl.bulkInsertExecution  - <==    Updates: 2
2022-08-15 21:45:39,940 1273  [           main] DEBUG ti.engine.impl.db.DbSqlSession  - inserting: Task[id=2505, name=创建出差申请]
2022-08-15 21:45:39,940 1273  [           main] DEBUG tity.TaskEntityImpl.insertTask  - ==>  Preparing: insert into ACT_RU_TASK (ID_, REV_, NAME_, BUSINESS_KEY_, PARENT_TASK_ID_, DESCRIPTION_, PRIORITY_, CREATE_TIME_, OWNER_, ASSIGNEE_, DELEGATION_, EXECUTION_ID_, PROC_INST_ID_, PROC_DEF_ID_, TASK_DEF_KEY_, DUE_DATE_, CATEGORY_, SUSPENSION_STATE_, TENANT_ID_, FORM_KEY_, CLAIM_TIME_, APP_VERSION_) values (?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) 
2022-08-15 21:45:39,941 1274  [           main] DEBUG tity.TaskEntityImpl.insertTask  - ==> Parameters: 2505(String), 创建出差申请(String), null, null, 创建出差申请(String), 50(Integer), 2022-08-15 21:45:39.911(Timestamp), null, employee(String), null, 2502(String), 2501(String), Leave:1:4(String), sid-d0797050-fe53-4ff7-8506-855ba3059d8d(String), null, null, 1(Integer), (String), null, null, null
2022-08-15 21:45:39,941 1274  [           main] DEBUG tity.TaskEntityImpl.insertTask  - <==    Updates: 1
2022-08-15 21:45:39,941 1274  [           main] DEBUG ti.engine.impl.db.DbSqlSession  - inserting: IdentityLinkEntity[id=2506, type=participant, userId=employee, processInstanceId=2501]
2022-08-15 21:45:39,941 1274  [           main] DEBUG kEntityImpl.insertIdentityLink  - ==>  Preparing: insert into ACT_RU_IDENTITYLINK (ID_, REV_, TYPE_, USER_ID_, GROUP_ID_, TASK_ID_, PROC_INST_ID_, PROC_DEF_ID_) values (?, 1, ?, ?, ?, ?, ?, ?) 
2022-08-15 21:45:39,942 1275  [           main] DEBUG kEntityImpl.insertIdentityLink  - ==> Parameters: 2506(String), participant(String), employee(String), null, null, 2501(String), null
2022-08-15 21:45:39,943 1276  [           main] DEBUG kEntityImpl.insertIdentityLink  - <==    Updates: 1

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

act_hi_actinst
在这里插入图片描述

act_hi_identitylink
在这里插入图片描述

act_hi_procinst
在这里插入图片描述

act_hi_taskinst
在这里插入图片描述

act_ru_execution
在这里插入图片描述

act_ru_identitylink

在这里插入图片描述

act_ru_task

在这里插入图片描述

任务查询

    /**
     * 查询当前个人待执行的任务
     */
    @Test
    public void testFindPersonalTaskList() throws Exception {
        // 任务负责人
// String assignee = "employee";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 创建TaskService
        TaskService taskService = processEngine.getTaskService();
        // 根据流程key和任务负责人查询任务
        List<Task> list = taskService.createTaskQuery()
                //流程Key
                .processDefinitionKey("Leave")
                //只查询该任务负责人的任务
//         .taskAssignee(assignee)
                .list();
        for (Task task : list) {
            System.out.println("流程实例id:" + task.getProcessInstanceId());
            System.out.println("任务id:" + task.getId());
            System.out.println("任务负责人:" + task.getAssignee());
            System.out.println("任务名称:" + task.getName());
        }
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

任务处理

    // 完成任务
    @Test
    public void completTask() {
        // 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取taskService
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                // 流程Key
                .processDefinitionKey("Leave")
                // 要查询的负责人
//         .taskAssignee("employee")  
                .singleResult();
        taskService.complete(task.getId());
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

流程查询

/**
 * 查询流程定义
 */
@Test
public void queryProcessDefinition() {
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取repositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey("Leave")
            .orderByProcessDefinitionVersion()
            .desc()
            .list();
    for (ProcessDefinition processDefinition : definitionList) {
        System.out.println("流程定义 id=" + processDefinition.getId());
        System.out.println("流程定义 name=" + processDefinition.getName());
        System.out.println("流程定义 key=" + processDefinition.getKey());
        System.out.println("流程定义 Version=" + processDefinition.getVersion());
        System.out.println("流程部署ID =" + processDefinition.getDeploymentId());
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
/**
 * 查询流程实例
 */
@Test
public void queryProcessInstance() {
    // 流程定义key
    String processDefinitionKey = "Leave";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取RunTimeService
    RuntimeService runtimeService = processEngine.getRuntimeService();
    List<ProcessInstance> list = runtimeService
            .createProcessInstanceQuery()
            .processDefinitionKey(processDefinitionKey)//
            .list();
<span class="token keyword">for</span> <span class="token punctuation">(</span>ProcessInstance processInstance <span class="token operator">:</span> list<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"----------------------------"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"流程实例id:"</span>
            <span class="token operator">+</span> processInstance<span class="token punctuation">.</span><span class="token function">getProcessInstanceId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"所属流程定义id:"</span>
            <span class="token operator">+</span> processInstance<span class="token punctuation">.</span><span class="token function">getProcessDefinitionId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"是否执行完成:"</span> <span class="token operator">+</span> processInstance<span class="token punctuation">.</span><span class="token function">isEnded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"是否暂停:"</span> <span class="token operator">+</span> processInstance<span class="token punctuation">.</span><span class="token function">isSuspended</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"当前活动标识:"</span> <span class="token operator">+</span> processInstance<span class="token punctuation">.</span><span class="token function">getActivityId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"业务关键字:"</span> <span class="token operator">+</span> processInstance<span class="token punctuation">.</span><span class="token function">getBusinessKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

流程历史信息查询

/**
 * 查看历史信息
 */
@Test
public void findHistoryInfo() {
    // 获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 获取HistoryService
    HistoryService historyService = processEngine.getHistoryService();
    HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
    instanceQuery.processInstanceId("2501");
    instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
    List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
    for (HistoricActivityInstance hi : activityInstanceList) {
        System.out.println("============="+hi.getActivityId()+" START=============");
        System.out.println(hi.getActivityId());
        System.out.println(hi.getActivityName());
        System.out.println(hi.getProcessDefinitionId());
        System.out.println(hi.getProcessInstanceId());
        System.out.println("============="+hi.getActivityId()+" END=============");
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

流程资源下载

@Test
public void downBpmnFile() throws IOException {
    // 1、得到引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取repositoryService
    RepositoryService repositoryService = processEngine.getRepositoryService();
    // 3、得到查询器:ProcessDefinitionQuery
    ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
            .processDefinitionKey("Leave")
            .singleResult();
    // 4、通过流程定义信息,得到部署ID
    String deploymentId = processDefinition.getDeploymentId();
    // 5、通过repositoryService的方法,实现读取图片信息和bpmn信息
     InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getDiagramResourceName());
    // bpmn文件的流
    InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, processDefinition.getResourceName());
    File file_png = new File("d:/Leave.png");
    File file_bpmn = new File("d:/Leave.bpmn20.xml");
    FileOutputStream bpmnOut = new FileOutputStream(file_bpmn);
    FileOutputStream pngOut = new FileOutputStream(file_png);
    IOUtils.copy(pngInput, pngOut);
    IOUtils.copy(bpmnInput, bpmnOut);
    pngOut.close();
    bpmnOut.close();
    pngInput.close();
    bpmnInput.close();
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Businesskey

这一章节我们来介绍这个businessKey,顾名思义,也就是业务关键字的意思。它是Activiti给我们设计的一个拓展点,可以根据业务场景,设计成不同的数据格式,比如json等,但是要注意这个字段的长度为255。

在这里插入图片描述

/**
 * 添加业务key
 */
@Test
public void addBusinessKey() {
    // 1、获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RuntimeService
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 3、启动流程的过程中,添加businesskey
    ProcessInstance instance = runtimeService.
            startProcessInstanceByKey("Leave", "businessNo");
    System.out.println("businessKey==" + instance.getBusinessKey());
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

流程变量

小例

再次回顾一下我们的流程图:
在这里插入图片描述

之前我们定义的请假流程,每个步骤都是非常固定的,但是生活中的业务流程,往往比较复杂。这里我们完善一下请假流程,请假3天以内由组长审批,3天以上需要增加经理审批。
在这里插入图片描述

针对这样的流程,就需要用到流程变量了。首先我们双击以下流程连线,填入UEL表达式。
在这里插入图片描述

在这里插入图片描述

同时修改每个任务节点的责任人为UEL表达式。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

添加测试代码

 /**
 * 启动流程的时候设置流程变量
 */
@Test
public void testStartProcessAndSetVariables() {
    // 1、获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RunTimeService
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 3、流程定义的Key
    String key = "Leave";
    // 4、流程变量的map
    Map<String, Object> variables = new HashMap<>();
    // 5、设置流程变量
    Evection evection = new Evection();
    // 6、设置请假日期
    evection.setDay(2d);
    // 7、把流程变量的pojo放入map
    variables.put("evection", evection);
    // 8、设定任务的负责人
    variables.put("employee", "小七");
    variables.put("TeamLeader", "第七人格");
    variables.put("Manager", "老李");
    // 9、启动流程
    runtimeService.startProcessInstanceByKey(key, variables);
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
/**
 * 完成个人任务
 */
@Test
public void completTaskByVariables() {
    completTaskByVariables("小七");
    completTaskByVariables("第七人格");
    completTaskByVariables("老李");
}

private void completTaskByVariables(String assingee) {
// 1、流程定义的Key
String key = “Leave”;
// 2、获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 3、获取taskService
TaskService taskService = processEngine.getTaskService();
// 4、查询任务
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assingee)
.singleResult();
if (task != null) {
taskService.complete(task.getId());
System.out.println(task.getId() + “----任务负责人:” + task.getAssignee() + “----任务已完成”);
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
作用域

上一节我们讲了一个关于流程变量的例子,这一节我们讲一讲流程变量的作用域。

  • Global变量
    这个是流程变量的默认作用域,作用于流程实例。上节中的例子就是Global变量变量,关键代码为:

启动流程时,设置变量

runtimeService.startProcessInstanceByKey(key,variables);

 
 
  • 1

办理任务时,设置变量

taskService.complete(任务id,variables); 

 
 
  • 1

通过当前流程实例,设置变量

runtimeService.setVariable(流程实例id, key, pojo对象); 

 
 
  • 1

通过当前任务,设置变量

taskService.setVariable(任务id, "evection", pojo对象)); 

 
 
  • 1
  • Local 变量
    这个作用域只针对一个任务或一个执行实例的范围,没有流程实例大。

关键代码为:

办理任务时,设置变量

taskService.setVariablesLocal(任务id,variables); 

 
 
  • 1

通过当前任务,设置变量

taskService.setVariableLocal(任务id, "evection", pojo对象)); 

 
 
  • 1
加餐

1、读者把出差时间变为2d试一试,看老李有没有进行审批。

2、建议读者都实验一下上面的api,加深印象。

网关

在画布中单击右键,选择网关,我们可以看到有以下四种网关
在这里插入图片描述

排他网关Exclusive Gateway

排他网关,顾名思义就是最终只会选择一个分支执行,是排他的。

并行网关Parallel Gateway

并行网关不会解析连线上的条件,并行网关中所有分支完成后,他才会走向下一个节点。

包含网关Inclusive Gateway

包含网关可以看做是排他网关和并行网关的结合体。有条件的分支选择条件执行,没有条件的分支,则必须执行。最终待这些分支完成后,他才会走向下一个节点。

事件网关Event Gateway

事件网关允许根据事件判断流向。这个网关生产中用的并不多,小七这里就不再展开了。

任务组

在流程变量那一节,我们给任务设置了负责人,但是在日常生活中,这个负责人有可能是指一类角色。

我们去掉负责人,并添加候选人:组长1,组长2
在这里插入图片描述

启动流程

/**
 * 启动流程的时候设置流程变量
 */
@Test
public void testStartProcessAndSetVariablesAboutGroup() {
    // 1、获取流程引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取RunTimeService
    RuntimeService runtimeService = processEngine.getRuntimeService();
    // 3、流程定义的Key
    String key = "Leave";
    // 4、流程变量的map
    Map<String, Object> variables = new HashMap<>();
    // 5、设置流程变量
    Evection evection = new Evection();
    // 6、设置请假日期
    evection.setDay(2d);
    // 7、把流程变量的pojo放入map
    variables.put("evection", evection);
    // 8、设定任务的负责人
    variables.put("employee", "小七");
    variables.put("Manager", "老李");
    // 9、启动流程
    runtimeService.startProcessInstanceByKey(key, variables);
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

完成任务

@Test
public void completTaskByVariablesAboutGroup() {
    // 测试组任务时,只执行这一行代码
    completTaskByVariables("小七");
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5

查询任务

/**
 * 查询组任务
 */
@Test
public void findGroupTaskList() {
    // 1、流程定义的Key
    String key = "Leave";
    // 2、任务候选人
    String candidateUser = "组长1";
    // 3、获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 4、获取TaskService
    TaskService taskService = processEngine.getTaskService();
    // 5、查询组任务
    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.getName());
        System.out.println("任务负责人=" + task.getAssignee());
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

绑定任务

/**
 * 候选人绑定任务
 */
@Test
public void claimTask() {
    // 1、获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取TaskService
    TaskService taskService = processEngine.getTaskService();
    // 3、当前任务的id
    String taskId = "5002";
    // 4、任务候选人
    String candidateUser = "组长1";
    // 5、查询任务
    Task task = taskService.createTaskQuery()
            .taskId(taskId)
            .taskCandidateUser(candidateUser)
            .singleResult();
    if (task != null) {
        // 6、绑定任务
        taskService.claim(taskId, candidateUser);
        System.out.println("taskId-" + taskId + "-用户-" + candidateUser + "-绑定任务完成");
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

归还任务

/**
 * 候选人归还任务
 */
@Test
public void testAssigneeToGroupTask() {
    // 1、获取引擎
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    // 2、获取TaskService
    TaskService taskService = processEngine.getTaskService();
    // 3、当前任务的id
    String taskId = "5002";
    // 4、任务负责人
    String assignee = "组长1";
    // 5、根据key 和负责人来查询任务
    Task task = taskService.createTaskQuery()
            .taskId(taskId)
            .taskAssignee(assignee)
            .singleResult();
    if (task != null) {
        // 6、归还任务 ,就是把负责人设置为空
        taskService.setAssignee(taskId, null);
        System.out.println("taskId-" + taskId + "-用户-" + assignee + "-归还任务完成");
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Activiti与Spring整合

Activiti与Spring整合的核心思想,就是将ProcessEngine的类交由Spring容器进行管理。

我们新建maven项目ActivitiSpring
在这里插入图片描述

在ActivitiSpring模块的pom中引入以下依赖

<dependencies>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <!-- activiti 与 Sring整合关键依赖 -->
    <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>
    <!-- mysql驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!-- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <!-- 链接池 -->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>${dbcp.version}</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>${commonsio.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</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>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.7.RELEASE</version>
    </dependency>
</dependencies>

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

然后在resources下新建配置文件activiti-spring.xml,填入以下内容

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- 数据源 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值