Activiti从0到1
概要:工作流引擎,实现业务表与工作流的分离,便于开发。
技术使用:采用activiti7版本,mysql数据库,Maven、idea2021、Activiti BPMNvisualizer插件,Camunda Modeler流程图设计器。
一、前期准备
1、Activiti BPMN visualizer插件安装
(一)setting的Plugins中搜索并点击installed
(二)在此处可看到创建BPMN文件、或者可以编辑即可
2、Camunda Modeler流程图设计器安装
问题:有了Activiti BPMN visualize为什么还要安装呢?
第一点:idea2021不能兼容常用的actiBPM。
第二点:Activiti BPMN visualize找不到加入监听器的功能(后续讲到)。
第三点:关于 assignee 失效。解决办法:将camunda 替换为 activiti,命名空间改为activity的命名空间,1、加入xmlns:activiti=“http://activiti.org/bpmn”,2、camunda改为activiti
(一)安装路径
链接:https://pan.baidu.com/s/10_W1VpduQXxCSitSKXxM7Q
提取码:6666
下载完成解压即可使用。
(二)idea配置Camunda Modeler
File > setting > Tools > External tool > 点击+号
(三)在此处可看见有新增的工具即可
3、创建项目后进行Maven配置
<!-- activiti 的相关包 mysql的驱动包 mybatis log4j 数据库链接池-->
<properties>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<activiti.version>7.0.0.Beta1</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn 模型处理 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-model</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn 转换 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-converter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn json数据转换 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-json-converter</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- bpmn 布局 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- activiti 云支持 -->
<dependency>
<groupId>org.activiti.cloud</groupId>
<artifactId>activiti-cloud-services-api</artifactId>
<version>${activiti.version}</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!-- 链接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
4、activiti配置文件(activiti.cfg.xml放于resource文件夹下)
<?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:///activiti?nullCatalogMeansCurrent=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="maxActive" value="3"/>
<property name="maxIdle" value="1"/>
</bean>
<!--在默认方式下 bean的id 固定为 processEngineConfiguration-->
<bean id="processEngineConfiguration"
class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<!--直接引用上面配置的链接池-->
<property name="dataSource" ref="dataSource"/>
<!--actviti数据库表在生成时的策略
true - 如果数据库中已经存在相应的表,那么直接使用,
如果不存在,那么会创建-->
<property name="databaseSchemaUpdate" value="true"/>
</bean>
</beans>
二、流程图制作
(一)首先创建一个bpmn2.0文件,然后编辑,上述有提到。
(二)右键可创建组件
(三)连线点击右上角的箭头并拖动到其他组件中
(四)创建完毕后可通过Camunda Modeler打开文件
(五)创建一个较为完整的流程图
(六)生成流程图片(方式一)
生成流程图片(方式二)
三、创建activiti表与了解其结构
(一)创建activiti表方式一:
1、使用方法getDefaultProcessEngine
2、默认从resources下读取名字为actviti.cfg.xml的文件
3、创建processEngine时,就会创建mysql的表
//默认方式
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment();
//获取流程引擎对象(此时创建activiti的表)
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
(二)创建activiti表方式二:
配置文件的名字可以自定义,bean的名字也可以自定义
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.
createProcessEngineConfigurationFromResource("activiti.cfg.xml","processEngineConfiguration");
//获取流程引擎对象(此时创建activiti的表)
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();
(三)了解activiti表结构
- act_hi_*:'hi’表示 history,历史数据。
- act_ge_*:'ge’表示 general,通用数据。
- act_evt_*:'evt’表示 event,事件日志。
- act_procdef_*:'procdef’表示processdefine,流程定义信息。
- act_re_*:'re’表示 repository,静态资源。
- act_ru_*:'ru’表示 runtime,表示运行时数据。
通用数据表:(ge)
表名 | 说明 |
---|---|
act_ge_bytearray | 存储通用的流程定义和流程资源 |
act_ge_bytearray | 存储整个流程引擎级别的数据 |
流程定义表:(re)
表名 | 说明 |
---|---|
act_re_model | 流程设计模型部署数据 |
act_re_deployment | 部署信息数据表 |
act_re_procdef | 流程定义数据 |
运行实例表:(ru)
表名 | 说明 |
---|---|
act_ru_deadletter_job | 作业失败超过重试次数部署数据 |
act_ru_event_subscr | 运行时事件数据 |
act_ru_execution | 运行时流程执行实例数据 |
act_ru_identitylink | 运行时用户信息数据 |
act_ru_integration | 运行时积分数据 |
act_ru_suspended_job | 运行时作业暂停数据 |
act_ru_task | 运行时任务信息数据 |
act_ru_timer_job | 运行时定时器作业表 |
act_ru_variable | 运行时变量信息表 |
act_ru_job | 运行时作业信息数据 |
历史流程表:(hi)
表名 | 说明 |
---|---|
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_evt_log | 通用事件日志记录数据 |
act_procdef_info | 流程定义的动态变更信息数据 |
四、流程部署
(一)流程部署方式一、
//1、创建(流程引擎)ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、获取RepositoryServcie(re表的服务层)\
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用service进行流程的部署,部署bpmn和png
Deployment deploy = repositoryService.createDeployment()
.name("出差申请流程")
.addClasspathResource("bpmn/evection.bpmn")
.addClasspathResource("bpmn/evection.png")
.deploy();
(二)、流程部署方式二、
//1、将png和bpmn打包成zip包
//2、创建(流程引擎)ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//3、获取RepositoryServcie(re表的服务层)\
RepositoryService repositoryService = processEngine.getRepositoryService();
//读取资源包文件,构造成inputStream
InputStream inputStream = this.getClass()
.getClassLoader()
.getResourceAsStream("bpmn/evection.zip");
//用inputStream 构造ZipInputStream
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
//使用压缩包的流进行流程的部署
Deployment deploy = repositoryService.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
(三)流程部署修改的表
1. ACT_RE_DEPLOYMENT(流程部署表)先创建7501部署表数据
2. ACT_GE_PROPERTY(流程定义表)后创建id为myEvection:1:7504的流程定义数据,myEvent是创建bpmn文件时定义的文件id,7501对应ACT_RE_DEPLOYMENT刚部署的记录id。注意:key相同时选取version最大的记录。
四、启动流程实例
(一)启动流程实例,先找到刚刚流程定义的key
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//3、根据流程定义的id启动流程
ProcessInstance instance = runtimeService.startProcessInstanceByKey("myEvection");
(二)启动流程修改的表
1. ACT_HI_TASKINST(历史任务实例数据表)
2. ACT_HI_PROCINST(历史流程实例数据表,正在执行的任务也在其中)
3. ACT_HI_ACTINST(历史节点数据,图片上的节点信息)
4. ACT_HI_IDENTITYLINK(历史流程用户信息数据表)
5. ACT_RU_EXECUTION(运行时流程执行实例数据表,一条是开始事件的执行实例,这个一直存在,只到流程结束后才会自动删除,is_active字段表示是否正在执行实例)
6. ACT_RU_TASK(运行时任务信息数据信息表)
五、查询个人代办任务
(一)代码实现
//1、获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、获取taskService
TaskService taskService = processEngine.getTaskService();
//3、根据流程key 和 任务的负责人 查询任务
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("myEvection") //流程Key
.taskAssignee("zhangsan") //要查询的负责人
.list();
//4、输出
for (Task task : taskList) {
System.out.println("流程实例id="+task.getProcessInstanceId());
System.out.println("任务Id="+task.getId());
System.out.println("任务负责人="+task.getAssignee());
System.out.println("任务名称="+task.getName());
}
(二)查询过程
1. 查询ACT_GE_PROPERTY(系统相关属性数据表,查询版本等相关信息,对于我们帮助不大)
2. 查询以下sql语句(ACT_RU_TASK 与 ACT_RE_PROCDEF关联查询)
select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = 'zhangsan' and D.KEY_ = 'myEvection' order by RES.ID_ asc LIMIT 2147483647 OFFSET 0
//查询结果如下
六、完成个人任务
(一)代码实现方式一(完成zhangsan的任务)、
//获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取操作任务的服务 TaskService
TaskService taskService = processEngine.getTaskService();
//完成任务,参数:任务id,完成zhangsan的任务,10005是上述ACT_RU_TASK表的id
taskService.complete("10005");
(二)代码实现方式二(完成其余三人的任务)、
//完成jerry的任务
//获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取操作任务的服务 TaskService
TaskService taskService = processEngine.getTaskService();
//获取jerry - myEvection 对应的任务
Task task = taskService.createTaskQuery()
.processDefinitionKey("myEvection")
.taskAssignee("jerry")
.singleResult();
System.out.println("流程实例id="+task.getProcessInstanceId());
System.out.println("任务Id="+task.getId());
System.out.println("任务负责人="+task.getAssignee());
System.out.println("任务名称="+task.getName());
//完成jerry的任务
taskService.complete(task.getId());
//输出
//流程实例id=10001
//任务Id=12502
//任务负责人=jerry
//任务名称=经理审批
//完成jack的任务
Task taskjack = taskService.createTaskQuery()
.processDefinitionKey("myEvection")
.taskAssignee("jack")
.singleResult();
System.out.println("流程实例id="+taskjack .getProcessInstanceId());
System.out.println("任务Id="+taskjack .getId());
System.out.println("任务负责人="+taskjack .getAssignee());
System.out.println("任务名称="+taskjack .getName());
//完成jack的任务
taskService.complete(task.getId());
//输出
//流程实例id=10001
//任务Id=15002
//任务负责人=jack
//任务名称=总经理审批
//完成rose的任务
Task taskjack = taskService.createTaskQuery()
.processDefinitionKey("myEvection")
.taskAssignee("rose")
.singleResult();
System.out.println("流程实例id="+taskjack .getProcessInstanceId());
System.out.println("任务Id="+taskjack .getId());
System.out.println("任务负责人="+taskjack .getAssignee());
System.out.println("任务名称="+taskjack .getName());
//完成jack的任务
taskService.complete(task.getId());
//输出
//流程实例id=10001
//任务Id=17502
//任务负责人=rose
//任务名称=财务审批
(三)完成个人任务修改的表、
1. ACT_HI_TASKINST(历史的任务实例表)
-
1、zhangsan完成任务(插入下一个jerry的任务实例,zhangsan任务实例end_time加入处理完结时间)
-
2、jerry完成任务(插入下一个jack的任务实例,jerry任务实例end_time加入处理完结时间)
-
3、jack完成任务(插入下一个rose的任务实例,jack任务实例end_time加入处理完结时间)
-
4、rose完成任务(插入结束的任务实例,任务实例end_time加入处理完结时间)
2. ACT_HI_ACTINST(历史节点数据)
- 1、zhangsan完成任务(插入下一个经理审批节点,节点中taskid为运行时任务信息表中的id,end_time加入处理完结时间)
- 2、jerry完成任务(插入下一个总经理节点,节点中taskid为运行时任务信息表中的id,end_time加入处理完结时间)
- 3、jack完成任务(插入下一个财务审批节点,节点中taskid为运行时任务信息表中的id,end_time加入处理完结时间)
- 4、rose完成任务(插入下一个结束节点,节点中taskid为运行时任务信息表中的id,end_time加入处理完结时间)
3. ACT_HI_IDENTITYLINK(历史流程用户信息数据表)
- 1、zhangsan完成任务(插入jerry负责人)
- 2、jerry完成任务(插入jack负责人)
- 3、jack完成任务(插入rose负责人)
4. ACT_RU_TASK(运行时任务信息数据信息表)
- 1、zhangsan完成任务(删除了10005zhangsan的创建出差申请任务,添加了经理审批任务记录)
- 2、jerry完成任务(删除了12502jerry的经理审批任务,添加了总经理审批任务记录)
- 3、jack完成任务(删除了15002jerry的总经理审批任务,添加了财务审批任务记录)
- 3、rose完成任务(删除了17502jack的财务审批任务)
5. ACT_RU_IDENTITYLINK(运行时用户信息数据)
- 1、zhangsan完成任务(插入jerry负责人)
- 2、jerry完成任务(插入jack负责人)
- 3、jack完成任务(插入rose负责人)***
负责人) - 4、rose完成任务(删除所有记录)
6. ACT_RU_EXECUTION(运行时流程执行实例数据表)
- 1、zhangsan完成任务(第二条记录改为_4id的节点(经理审批))
- 2、jerry完成任务(第二条记录改为_5id的节点(总经理经理审批))
- 3、jack完成任务(第二条记录改为_6id的节点(财务审批))
- 4、rose完成任务(第一、二条记录删除细节):
- 第一步先更改第二条记录REV为5、ACT_ID_为_7(结束节点)
- 第二步删除id为10002的记录。
- 第三步删除结束节点,id为10001的记录。
7. ACT_HI_PROCINST(历史流程实例数据表)
- 4、rose完成任务:end_time更新为完成时间、end_act_id_更新为最后一个节点的id
七、查看历史信息
(一)代码实现
//获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取HistoryService
HistoryService historyService = processEngine.getHistoryService();
//获取 actinst表的查询对象
HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
//查询 actinst表,条件:根据 InstanceId 查询
//instanceQuery.processInstanceId("2501");
//查询 actinst表,条件:根据 DefinitionId 查询
instanceQuery.processDefinitionId("myEvection:1:7504");
//增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//查询所有内容
List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
//输出
for (HistoricActivityInstance hi : activityInstanceList) {
System.out.println(hi.getActivityId());
System.out.println(hi.getActivityName());
System.out.println(hi.getProcessDefinitionId());
System.out.println(hi.getProcessInstanceId());
System.out.println("<==========================>");
}
输出:
_2
StartEvent
myEvection:1:7504
10001
<==========================>
_3
创建出差申请
myEvection:1:7504
10001
<==========================>
_4
经理审批
myEvection:1:7504
10001
<==========================>
_5
总经理审批
myEvection:1:7504
10001
<==========================>
_6
财务审批
myEvection:1:7504
10001
<==========================>
_7
EndEvent
myEvection:1:7504
10001
<==========================>
八、与业务表关联
(一)代码实现(使用关联id启动流程)
//1、获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、获取RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3、启动流程的过程中,添加businesskey
//第二个参数:businessKey,业务表的id,就是1001
ProcessInstance instance = runtimeService.
startProcessInstanceByKey("myEvection", "1001");
//4、输出
System.out.println("businessKey=="+instance.getBusinessKey());
输出
businessKey==1001
(二)与普通方式启动实例比较
1. ACT_HI_PROCINST(历史流程实例数据表比较,普通启动business_key为空,说明业务表的id存在这个字段中)
2. ACT_RU_EXECUTION(运行时流程执行实例数据表比较,普通启动business_key为空,说明业务表的id存在这个字段中)
九、使用uel设置负责人
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现:
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、获取RepositoryServcie
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用service进行流程的部署,定义一个流程的名字,把bpmn和png部署到数据中
Deployment deploy = repositoryService.createDeployment()
.name("出差申请流程-uel")
.addClasspathResource("bpmn/uel.bpmn")
.deploy();
//4、输出部署信息
System.out.println("流程部署id="+deploy.getId());
System.out.println("流程部署名字="+deploy.getName());
输出:
流程部署id=25001
流程部署名字=出差申请流程-uel
act_re_procdef表结果:
(三)流程启动代码实现:
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//设定assignee的值,用来替换uel表达式
Map<String,Object> assigneeMap = new HashMap<>();
assigneeMap.put("assignee0","张三");
assigneeMap.put("assignee1","李经理");
assigneeMap.put("assignee2","王总经理");
assigneeMap.put("assignee3","赵财务");
//启动流程实例
runtimeService.startProcessInstanceByKey("myEvection1",assigneeMap);
(四)添加uel表达式后,额外修改的表
1. ACT_HI_VARINST(历史流程运行中的变量信息数据表)
2. ACT_RU_VARIABLE(运行时变量表)
注:其余表的修改与普通流程启动相同
十、候选人实例介绍
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现:
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、获取RepositoryServcie
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用service进行流程的部署,定义一个流程的名字,把bpmn和png部署到数据中
Deployment deploy = repositoryService.createDeployment()
.name("出差申请流程-Candidate")
.addClasspathResource("bpmn/evection-candidate.bpmn")
.deploy();
- act_re_procdef表结果:
(三)流程启动代码实现:
//获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.startProcessInstanceByKey("testCandidate");
说明:除了部门经理审批,其余流程与第六章相同。
(四)查询组任务代码实现(提前将五好青年1完成任务,到达部门经理审批):
//获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//查询组任务
List<Task> taskList = taskService.createTaskQuery()
.processDefinitionKey("testCandidate")
.taskCandidateUser("wangwu") //根据候选人查询任务
.list();
for (Task task : taskList) {
System.out.println("========================");
System.out.println("流程实例ID="+task.getProcessInstanceId());
System.out.println("任务id="+task.getId());
System.out.println("任务负责人="+task.getAssignee());
}
输出
========================
流程实例ID=55001
任务id=57502
任务负责人=null
- ACT_RU_TASK结果(当前负责人为空):
- ACT_HI_ACTINST结果(部门经理审批负责人为空):
- ACT_HI_TASKINST结果 (部门经理审批负责人为空):
(五)wangwu拾取任务代码实现:
//获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//当前任务的id
String taskId = "57502";
//任务候选人
String candidateUser = "wangwu";
// 查询任务
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskCandidateUser(candidateUser)
.singleResult();
if(task != null){
// 拾取任务
taskService.claim(taskId,candidateUser);
System.out.println("taskid-"+taskId+"-用户-"+candidateUser+"-拾取任务完成");
}
输出:
taskid-57502-用户-wangwu-拾取任务完成
- ACT_RU_TASK结果图(回归正常流程):
- ACT_HI_ACTINST结果(回归正常流程):
- ACT_HI_TASKINST结果 (回归正常流程):
(五)wang归还任务、交接任务代码实现:
总的来说就是改assignee_字段
归还任务设置成null
交接任务设置成lisi
//获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取TaskService
TaskService taskService = processEngine.getTaskService();
//当前任务的id
String taskId = "57502";
//任务负责人
String assignee = "wangwu";
//根据key 和负责人来查询任务
Task task = taskService.createTaskQuery()
.taskId(taskId)
.taskAssignee(assignee)
.singleResult();
if(task != null){
//归还任务 ,就是把负责人 设置为空
taskService.setAssignee(taskId,null);
taskService.setAssignee(taskId,'lisi');
System.out.println("taskid-"+taskId+"-归还任务完成");
}
(六)后续完成任务按照第六章正常思路完成
十一、监听器
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment()
.name("测试监听器")
.addClasspathResource("bpmn/demo-listen.bpmn")
.deploy();
- act_re_procdef表结果:
(二)启动流程代码实现
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.startProcessInstanceByKey("testListener");
- ACT_RU_TASK结果图
- ACT_HI_ACTINST结果
- ACT_HI_TASKINST结果 (回归正常流程):
问题来了,为什么ACT_RU_TASK中的负责人是张三呢?
这就是监听器的作用,我在图中设置了监听器的路径,一旦开始流程便开始调用监听类中的notify方法。代码如下
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
public class MyTaskListener implements TaskListener {
//delegateTasK是当前任务的对象
@Override
public void notify(DelegateTask delegateTask) {
//默认是create事件
if("创建申请".equals(delegateTask.getName()) &&
"create".equals(delegateTask.getEventName())){
delegateTask.setAssignee("张三");
}
}
}
十二、设置变量
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deploy = repositoryService.createDeployment()
.name("出差申请流程-variables")
.addClasspathResource("bpmn/evection-global.bpmn")
.deploy();
- act_re_procdef表结果:
(三)主体类准备(必须继承Serializable ,不然bpmn文件无法识别变量)
/**
* 出差申请中的流程变量对象
*/
public class Evection implements Serializable {
private Long id;
private String evectionName;
private Double num;
private String reson;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEvectionName() {
return evectionName;
}
public void setEvectionName(String evectionName) {
this.evectionName = evectionName;
}
public Double getNum() {
return num;
}
public void setNum(Double num) {
this.num = num;
}
public String getReson() {
return reson;
}
public void setReson(String reson) {
this.reson = reson;
}
}
(四)流程启动代码实现方式一(启动流程的时候设置流程变量):
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
//流程变量的map
Map<String,Object> variables = new HashMap<>();
//设置流程变量
Evection evection = new Evection();
//设置出差日期
evection.setNum(2d);
//把流程变量的pojo放入map
variables.put("evection",evection);
//设定任务的负责人
variables.put("assignee0","李四");
variables.put("assignee1","王经理");
variables.put("assignee2","杨总经理");
variables.put("assignee3","张财务");
//启动流程
runtimeService.startProcessInstanceByKey("myEvection2",variables);
(五)流程启动代码实现方式二(完成个人任务的时候设置流程变量):
//设置流程变量
Evection evection = new Evection();
//设置出差时间
evection.setNum(2d);
Map<String,Object> map = new HashMap<>();
map.put("evection",evection);
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
//查询任务
Task task = taskService.createTaskQuery()
.processDefinitionKey("myEvection2")
.taskAssignee("李四")
.singleResult();
if(task != null){
//根据任务id 完成任务,并传递流程变量
taskService.complete(task.getId(),map);
System.out.println(task.getId()+"----任务已完成");
};
(六)添加流程变量修改的表,除了ACT_HI_VARINST其余表正常执行
1. ACT_HI_VARINST(历史流程运行中的变量信息数据表)
说明:图中的evection.num就是代码中设置的2d
(七)以(ACT_RU_TASK表、方式一)为代表简述执行过程:
第一步:李四送审后表结果
第二步:王经理送审后表结果(可见直接跳过了杨总经理,直接到了张财务,说明图中的变量表达式生效,天数小于2不需要杨总经理审批)
第三步:张财务送审后表结果(所有记录删除)
注:若两个条件均满足要求,则走flowid最小的任务。都不符合条件,流程结束
十三、排他网关
简介:所有分支都会判断条件是否为true,如果为true就执行该分支
注意:只会选择一个true的分支执行,如果都满足条件,则走flowid最小的任务。
与上述条件变量的区别:都不满足条件,则抛出异常。
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/evection-exclusive.bpmn")
.name("出差申请流程-排他网关")
.deploy();
- act_re_procdef表结果:
(三)流程启动代码实现:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String, Object> map = new HashMap<>();
Evection evection = new Evection();
evection.setNum(2d);
//定义流程变量,把出差pojo对象放入map
map.put("evection",evection);
//启动流程实例,并设置流程变量的值(把map传入)
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("exclusive", map);
- ACT_RU_TASK表结果:
ACT_RU_VARIABLE表结果:
(三)以(ACT_RU_TASK表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:jerry送审后表结果(经过判断到达财务审批rose负责人手上)
第三步:rose送审后表结果(记录删除)
十四、并行网关
可以把多条分支汇聚一起,会走所有的分支、还要等多个分支完成才可继续完成。
注意:并行网关不会解析条件,即使定义了条件也会被忽略。
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/evection-parallel.bpmn")
.name("出差申请流程-并行网关")
.deploy();
- act_re_procdef表结果:
(三)流程启动代码实现:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String, Object> map = new HashMap<>();
Evection evection = new Evection();
evection.setNum(4d);
map.put("evection",evection);
//启动流程实例,并设置流程变量的值(把map传入)
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("parallel", map);
ACT_RU_TASK表结果:
ACT_RU_EXECUTION表结果:
ACT_RU_VARIABLE表结果:
(三)以(ACT_RU_TASK表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:jerry送审后表结果
第三步:jack送审后表结果
第四步:rose送审后表结果(记录删除)
(四)以(ACT_RU_EXECUTION表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:jerry送审后表结果(项目经理审批到达汇聚节点)
第三步:jack送审后表结果
第四步:rose送审后表结果(记录删除)
(五)以(ACT_HI_TASKINST表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:jerry送审后表结果(jerry加上了end_time)
第三步:jack送审后表结果(添加总经理审批节点)
第四步:rose送审后表结果
(六)以(ACT_HI_PROCINST表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:jerry送审后表结果
第三步:jack送审后表结果
第四步:rose送审后表结果
(七)以(ACT_HI_ACTINST表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:jerry送审后表结果(技术经理审批endtime更新,汇聚节点创建)
第三步:jack送审后表结果(因为请4天假期,所以,再添加一个并行网关节点,添加一个总经理审批节点)
第四步:rose送审后表结果
十五、包含网关
排他网关和并行网关的结合。都为ture的时候,都要执行任务,并且最后汇聚在一起才可以执行下去。
(一)重新创建bpmn文件,如下图
(二)流程部署代码实现:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("bpmn/evection-inclusive.bpmn")
.name("出差申请流程-包含网关")
.deploy();
- act_re_procdef表结果:
(三)流程启动代码实现:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
String key = "inclusive";
Map<String, Object> map = new HashMap<>();
Evection evection = new Evection();
evection.setNum(4d);
//定义流程变量,把出差pojo对象放入map
map.put("evection",evection);
//启动流程实例,并设置流程变量的值(把map传入)
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(key, map);
ACT_RU_TASK表结果:
ACT_RU_EXECUTION表结果:
ACT_RU_VARIABLE表结果:
(三)以(ACT_RU_TASK表)为代表简述执行过程:
第一步:tom送审后表结果(过滤了技术经理审批)
第二步:miki送审后表结果
第三步:jack送审后表结果
第四步:rose送审后表结果(记录删除)
(四)以(ACT_RU_EXECUTION表)为代表简述执行过程:
第一步:tom送审后表结果(技术经理节点不在)
第二步:miki送审后表结果(项目经理审批到达汇聚节点)
第三步:jack送审后表结果
第四步:rose送审后表结果(记录删除)
(五)以(ACT_HI_TASKINST表)为代表简述执行过程:
第一步:tom送审后表结果(技术经理节点不在)
第二步:miki送审后表结果(miki加上了end_time)
第三步:jack送审后表结果(添加总经理审批节点)
第四步:rose送审后表结果
(六)以(ACT_HI_ACTINST表)为代表简述执行过程:
第一步:tom送审后表结果
第二步:miki送审后表结果(技术经理审批endtime更新,汇聚节点创建)
第三步:jack送审后表结果(因为请4天假期,所以,再添加一个并行网关节点,添加一个总经理审批节点)
第四步:rose送审后表结果