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送审后表结果






































