什么是流程实例
参与者(可以是用户也可以是程序)按照流程定义内容发起一个流程,这就是一个流程实例。是动
态的。
流程定义部署在 activiti 后,就可以在系统中通过 activiti 去管理该流程的执行,执行流程表示流
程的一次执行。
多个用户可同时执行该流程,每个执行互不影响,每个执行是单独的流程实例
流程实例的部署与启动
1 /**
2 * 流程变量的测试---新的请假流程定义的部署
3 * 1.得到ProcessEngine
4 * 2.得到ReposuitoryService对象
5 * 3.实现部署
6 *
7 */
8
9 public static void main(String[] args) {
10 /* ProcessEngine ProcessEngine = ProcessEngines.getDefaultProcessEngine();
11 RepositoryService repositoryService = ProcessEngine.getRepositoryService();
12 Deployment deployment = repositoryService.createDeployment()
13 .addClasspathResource("diagram/holiday4.bpmn")
14 .addClasspathResource("diagram/holiday4.png").name("请假流程-流程变量")
15 .deploy();
16 System.out.println(deployment.getId());
17 System.out.println(deployment.getName());*/
18 //流程实例的启动
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday"); System.out.println("流程定义ID"+processInstance.getProcessDefinitionId()); //92503 System.out.println("流程实例ID"+processInstance.getId());
19
BussinessKey 业务标识
启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey
Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业
务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据
1 /**
2 * 添加bussinessKey
3 * 1.得到ProcenessEngine
4 * 2.得到RuntimeService
5 * 3.管理流程实例,指定业务标识bussinessKey
6 * ---params 流程定义的key ,业务标识bussinessKey
7 * 4.输出processInstance属性
8 *
9 * 本质:act_ru_execution表的bussinessKey要存入标识
10 *
11 */
12
13
14 public static void main(String[] args) {
15 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
16 RuntimeService runtimeService = processEngine.getRuntimeService();
17 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holiday", "1001");
18
19 System.out.println(processInstance.getBusinessKey());
20 }
挂起、激活流程实例
由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行
全部流程实例挂起
1 /**
2 * 全部流程的挂起和激活
3 * 1.得到ProcessEngine对象
4 * 2.得到RepositoryService
5 * 3.查询流程定义对象
6 * 4.得到当前流程定义是否为暂停状态
7 * 5.判断
8 */
9 public static void main(String[] args) {
10 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
11 RepositoryService repositoryService = processEngine.getRepositoryService();
12 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("请假流程").singleResult();
13 boolean suspended = processDefinition.isSuspended();
14
15 String processDefinitionId = processDefinition.getId();
16
17 if (suspended){
18 repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
19 System.out.println("流程定义:"+processDefinitionId+"激活");
20 }else {
21 repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
22 System.out.println("流程定义:"+processDefinitionId+"挂起");
23 }
24
25
26
27 }
单个流程执行挂起操作,某个流程实例挂起则此流程不再继续执行
/** 1.得到processEngine
* 2.获取RuntimeService
* 3.根据流程实例id查询流程实例
* 4.判段
*/
public static void main(String[] args) {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
.processInstanceId("35001").singleResult(); //act_ru_execution
boolean suspended = processInstance.isSuspended();
String processInstanceId = processInstance.getId();
if (suspended){
runtimeService.activateProcessInstanceById(processInstanceId);;
System.out.println("流程定义"+processInstanceId+"激活");
}else {
runtimeService.suspendProcessInstanceById(processInstanceId);
System.out.println("流程定义"+processInstanceId+"挂起");
}
个人任务
固定分配
Assigneee:任务负责人
表达式分配
UEL 表达式 activiti 支持两个 UEL 表达式: UEL-value 和 UEL-method, assignee 这个变量是 activiti 的一个流程变量
${ldapService.findManagerForEmployee(emp)}
ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti
流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中
表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。
如下:
${order.price > 100 && order.price < 250}
使用流程变量分配任务
start -》 填写请假申请单 -》部门经理审批 -》总经理审批 -》end
设部门经理审批的Assignee 为 ${assignee}
1.自动流程实例
/**
*自动流程实例
* 1.得到ProcessEngine
* 2.得到RuntimeService
* 3.设置assignee的取值,用户可以在界面上设置流程执行人
* 4.启动流程实例,同时设置流程定义的assignee的值
* 5.输出
*/
public static void main(String[] args) {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String,Object> map = new HashMap<>();
map.put("assignee","zhangsan");
ProcessInstance processInstance =
runtimeService.startProcessInstanceByKey("holiday2", map);
}
监听器分配
Task Listeners
Create:任务创建后触发
Assignment:任务分配后触发
Delete:任务完成后触发
All:所有事件发生都触发
定义任务监听类,且类必须实现 org.activiti.engine.delegate.TaskListener 接口
流程变量
流程变量就是 activiti 在管理工作流时根据管理需要而设置的变量 
如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无
法反序列化,需要生成 serialVersionUID
流程变量的作用域默认是一个流程实例(processInstance),也可以是一个任务(task)或一个执行实例
(execution),这三个作用域流程实例的范围最大,可以称为 global 变量,任务和执行实例仅仅是针对
一个任务和一个执行实例范围,范围没有流程实例大, 称为 local 变量。
设置流程变量
通过UEL表达式使用流程变量
1.在assignee处设置uel表达式,表达式的值为任务的负责人
2.在连线上设置uel表达式,决定流程走向
uel为true,决定流程走向
使用 Global 变量控制流程
需求:员工创建请假申请单,由部门经理审核,部门经理审核通过后请假 3 天及以下由人事经理直接
审核, 3 天以上先由总经理审核,总经理审核通过再由人事经理存档

Holiday
1 public class Holiday implements Serializable {
2
3 private Integer id;
4 private String holidayName;
5 private Date beginDate;
6 private Date endDate;
7 private Float num;
8 private String reason;
9 private String type;
10
11 //getter
12 //setter
13
16
17 }
启动流程时设置
在启动流程时设置流程变量,变量的作用域是整个流程实例
/**
* 流程变量的测试---新的请假流程定义的部署
* 1.得到ProcessEngine
* 2.得到ReposuitoryService对象
* 3.实现部署
*
*/
public static void main(String[] args) {
/* ProcessEngine ProcessEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = ProcessEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("diagram/holiday4.bpmn")
.addClasspathResource("diagram/holiday4.png").name("请假流程-流程变量")
.deploy();
System.out.println(deployment.getId());
System.out.println(deployment.getName());*/
/**
* 启动流程实例,设置流程变量
* 1.得到ProcessEngine
* 2.得到RuntimeService
* 3.流程定义的key myProcess_1
* act_ge_bytearray
* act_ru_variable
*/
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
String key = "myProcess_1";
Map<String,Object> map = new HashMap<>();
Holiday holiday = new Holiday();
holiday.setNum(1F);
map.put("holiday",holiday);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, map);
System.out.println(processInstance.getProcessDefinitionId());
}
startProcessInstanceByKey(processDefinitionKey, variables)流程变量作用域是一个流程实例,流程变量使用 Map 存储,同一个流程实例设置变量 map 中 key 相同,后者覆盖前者
任务办理时设置
1 public static void main(String[] args) {
2
3 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
4 TaskService taskService = processEngine.getTaskService();
5 String key = "myProcess_1";
6 Task task = taskService.createTaskQuery().processDefinitionKey(key)
7 .taskAssignee("zhangsan").singleResult();
8
9 Map<String,Object> map = new HashMap<>();
10
11 Holiday holiday = new Holiday();
12 holiday.setNum(5F);
13
14 map.put("holiday",holiday);
15 if (task != null){
16 taskService.complete(task.getId(),map);
17 System.out.println("任务执行完成");
18 }
19 }
3.通过当前流程实例设置
1 /**
2 *通过流程实例ID设置全局变量
3 *1.得到ProcessEngine
4 * 2.得到RuntimeService
5 * 3.流程定义的key问题
6 * 4.通过实例id,来设置流程变量
7 * 参数:流程实例的id,流程变量名,流程变量名所对应的值
8 * 5.
9 */
10
11
12 /* //流程实例的定义
13 public static void main(String[] args) {
14
15 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
16
17 RuntimeService runtimeService = processEngine.getRuntimeService();
18
19 String key = "myProcess_1";
20
21
22 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key);
23
24 System.out.println(processInstance.getProcessDefinitionId());
25 System.out.println(processInstance.getId()); //流程实例的id 70001
26
27
28 }*/
29
30 public static void main(String[] args) {
31
32 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
33
34 RuntimeService runtimeService = processEngine.getRuntimeService();
35
36 String key = "myProcess_1";
37 Holiday holiday = new Holiday();
38 holiday.setNum(5F);
39
40 runtimeService.setVariable("70001","holiday",holiday);
41
42
43 }
executionId 必须当前未结束 流程实例的执行 id,通常此 id 设置流程实例 的 id。
4.通过当前任务设置
gloal 变量
taskService.setVariblesLocal(......)
组任务
设置多个候选人,可以从候选人中选择参与者来完成任务
使用activiti:candiateUsers=”用户 1,用户 2,用户 3”的这种方式来实现设置一组候选人
组任务的办理流程
1.查询组任务
2.拾取(claim)任务
3.查询个人任务
4.办理个人任务
场景
start -> 填写请假单 -》部门经理审批(Candidate User : zhangsa,lisi) -》总经理
1.部署流程定义 2.启动流程实例
用户组查询任务
1 /**
2 * 1.得到ProcessEngine
3 * 2.得到TaskService
4 * 3.设置一些参数,流程
5 * 4.执行查询
6 */
7 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
8 TaskService taskService = processEngine.getTaskService();
9
10 String key = "myProcess_1";
11 String candidate_users = "zhangsan";
12 List<Task> list = taskService.createTaskQuery()
13 .processDefinitionKey(key)
14 .taskCandidateUser(candidate_users) //设置候选用户
15 .list();
16
17 for (Task task : list){
18 System.out.println(task.getProcessInstanceId());
19 System.out.println(task.getId());
20 System.out.println(task.getName());
21 System.out.println(task.getAssignee());
22 }
用户拾取任务
//拾取任务的过程就是将候选选用户转化为真正任务的负责人(让任务的assignee有值)
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
String key = "myProcess_1";
String candidate_users = "zhangsan";
Task task = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskCandidateUser(candidate_users)
.singleResult();
if (task != null){
taskService.claim(task.getId(),candidate_users);//(参数任务的ID,具体的候选用户名)
System.out.println("任务拾取完毕");
}
用户查询自己的任务
//当前的用户查询自己的任务
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
String key = "myProcess_1";
String assignee = "zhangsan";
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey(key)
.taskAssignee(assignee)
.list();
for (Task task : list){
System.out.println(task.getProcessInstanceId());
System.out.println(task.getId());
System.out.println(task.getName());
System.out.println(task.getAssignee());
}
用户办理个人任务
1 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
2 TaskService taskService = processEngine.getTaskService();
3 String key = "myProcess_1";
4 String assignee="zhangsan";
5 Task task = taskService.createTaskQuery()
6 .processDefinitionKey(key)
7 .taskAssignee(assignee) //设置任务的负责人
8 .singleResult();
9
10 if (task != null){
11 taskService.complete(task.getId());
12 System.out.println("任务执行完毕!");
13 }
归还组任务
1 TaskService taskService = processEngine.getTaskService();
2 // 当前待办任务
3 String taskId = "6004";
4 // 任务负责人
5 String userId = "zhangsan2";
6 // 校验userId是否是taskId的负责人,如果是负责人才可以归还组任务
7 Task task = taskService.createTaskQuery().taskId(taskId)
8 .taskAssignee(userId).singleResult();
9 if (task != null) {
10 // 如果设置为null,归还组任务,该 任务没有负责人
11 taskService.setAssignee(taskId, null);
任务交接
任务交接,任务负责人将任务交给其它候选人办理该任务
1 //8.任务交接,前提要保证当前用户是这个任务的负责人,这时候他才可以有权限去将任务交接给其他候选人
2 public static void main(String[] args) {
3 //1.得到ProcessEngine对象
4 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
5
6 //2.得到TaskService对象
7 TaskService taskService = processEngine.getTaskService();
8
9 //3.设置一些参数,流程定义的key,用户
10 String key = "myProcess_1";
11 String assignee="zhangsan";
12
13 //4.执行查询
14 Task task = taskService.createTaskQuery()
15 .processDefinitionKey(key)
16 .taskAssignee(assignee) //设置任务的负责人
17 .singleResult();
18 //5.判断是否有这个任务
19 if(task!=null){
20 taskService.setAssignee(task.getId(),"lisi");//交接任务为lisi ,交接任务就是一个候选人拾取用户的过程
21 System.out.println("交接任务完成~!");
22 }
23 }
网关
排他网关(也叫异或(XOR)网关,或叫基于数据的排他网关),用来在流程中实现决策。 当流程
执行到这个网关,所有分支都会判断条件是否为 true,如果为 true 则执行该分支
在condition上设置条件
排他网关只会选择一个为 true 的分支执行

部署流程定义
//1.部署流程定义
public static void main(String[] args) {
//1.创建ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3.进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("diagram/day05/holiday5.bpmn") //添加bpmn资源
//.addClasspathResource("diagram/holiday5.png")
.name("请假申请单流程")
.deploy();
//4.输出部署的一些信息
System.out.println(deployment.getName());
System.out.println(deployment.getId());
}
启动流程实例
1 public static void main(String[] args) {
2 //1.得到ProcessEngine对象
3 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
4
5 //2.得到RunService对象
6 RuntimeService runtimeService = processEngine.getRuntimeService();
7
8 Holiday holiday = new Holiday();
9 holiday.setNum(5F);
10 Map<String,Object> map = new HashMap<>();
11 map.put("holiday",holiday);//流程变量赋值
12
13 //3.创建流程实例 流程定义的key需要知道 holiday
14 ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayExclusive",map);
15
16
17 //4.输出实例的相关信息
18 System.out.println("流程定义ID"+processInstance.getProcessDefinitionId());//holiday:1:4
19 System.out.println("流程实例ID"+processInstance.getId());//2501
20 }
依次执行任务
public static void main(String[] args) {
//1.得到ProcessEngine对象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2.得到TaskService对象
TaskService taskService = processEngine.getTaskService();
//3.查询当前用户的任务
Task task = taskService.createTaskQuery()
.processDefinitionKey("holidayExclusive")
.taskAssignee("zhangsan")
.singleResult();
//4.处理任务,结合当前用户任务列表的查询操作的话,任务ID:task.getId()
if(task!=null){
taskService.complete(task.getId());
System.out.println("用户任务执行完毕...");
}
并行网关
并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进
入和外出顺序流的
fork 分支:
并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。
join 汇聚:
所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通
过汇聚网关
并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略

财务结算和入库是两个 execution 分支,在 act_ru_execution 表有两条记录分别是财务结算和入库,
act_ru_execution 还有一条记录表示该流程实例。
待财务结算和入库任务全部完成,在汇聚点汇聚,通过 parallelGateway 并行网关。
并行网关在业务应用中常用于会签任务,会签任务即多个参与者共同办理的任务
包含网关
包含网关可以看做是排他网关和并行网关的结合体。 和排他网关一样,你可以在外出顺序流上
定义条件,包含网关会解析它们。 但是主要的区别是包含网关可以选择多于一条顺序流,这和并行
网关一样。
包含网关的功能是基于进入和外出顺序流的:
分支
所有外出顺序流的条件都会被解析,结果为 true 的顺序流会以并行方式继续执行, 会为每个顺序流 创建一个分支。
汇聚
所有并行分支到达包含网关,会进入等待状态, 直到每个包含流程 token 的进入顺序流的分支都到达。 
先走到汇聚结点的分支,要等待其它分支走到汇聚。
等所有分支走到汇聚,包含网关就执行完成。包含网关执行完成,分支和汇聚就从act_ru_execution删除
完