楔子
本文主要介绍了 Activiti 的相关使用与集成,适合想要学习 Activiti 的读者食用。
Activiti 介绍
Activiti 是目前使用最为广泛的开源工作流引擎之一,在小七 2017 年走向程序员这一条不归路的时候,它就已经是开源工作流引擎的老大哥了。
Activiti 官网
学习一门新技术/新框架,我们第一件事就是从它的官网入手,下面贴出 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"><!-- 这里可以使用 链接池 dbcp--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>bean</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">></span></span> <span class="token comment"><!-- 引用数据源 上面已经设置好了--></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token comment"><!-- activiti 数据库表处理策略 --></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</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">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>bean</span><span class="token punctuation">></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