2021全网最全Activiti7教程04(Activiti7进阶篇-欢迎收藏)

  • Post author:
  • Post category:其他




前言

很久没有发过文章,今天来说一下应届生找工作的问题吧,就算你是打摆子都要看完~~

金九银十是社招以及校招的火热时期,但今年很明显没有往年般的火热,面试也是越来越难了。对于应届生来说,如何能够在面试官眼中脱颖而出显得尤为重要。好在,我帮你们找到了一份非常全面的面试资料,针对于应届生以及转行过来的人群都是极具价值的,接下来就一起看看这份笔记。

// 获取TaskService

TaskService taskService = processEngine.getTaskService();

List taskList = taskService.createTaskQuery()

.processDefinitionKey(processDefinitionKey)

.includeProcessVariables()

.taskAssignee(assignee)

.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());

System.out.println(“任务名称: ” + task.getName());

}

}



[](()关联 businessKey

需求:

在 activiti 实际应用时,查询待办任务可能要显示出业务系统的一些相关信息。

比如:查询待审批出差任务列表需要将出差单的日期、 出差天数等信息显示出来。

出差天数等信息在业务系统中存在,而并没有在 activiti 数据库中存在,所以是无法通过 activiti 的 api 查询到出差天数等信息。

实现:

在查询待办任务时,通过 businessKey(业务标识 )关联查询业务系统的出差单表,查询出出差天数等信息。

@Test

public void findProcessInstance(){

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取TaskService

TaskService taskService = processEngine.getTaskService();

// 获取RuntimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 查询流程定义的对象

Task task = taskService.createTaskQuery()

.processDefinitionKey(“myEvection1”)

.taskAssignee(“张三”)

.singleResult();

// 使用task对象获取实例id

String processInstanceId = task.getProcessInstanceId();

// 使用实例id,获取流程实例对象

ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()

.processInstanceId(processInstanceId)

.singleResult();

// 使用processInstance,得到 businessKey

String businessKey = processInstance.getBusinessKey();

System.out.println(“businessKey==”+businessKey);

}



[](()2.3 办理任务

注意:在实际应用中,完成任务前需要校验任务的负责人是否具有该任务的办理权限 。

/**

  • 完成任务,判断当前用户是否有权限

*/

@Test

public void completTask() {

//任务id

String taskId = “15005”;

// 任务负责人

String assingee = “张三”;

//获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 创建TaskService

TaskService taskService = processEngine.getTaskService();

// 完成任务前,需要校验该负责人可以完成当前任务

// 校验方法:

// 根据任务id和任务负责人查询当前任务,如果查到该用户有权限,就完成

Task task = taskService.createTaskQuery()

.taskId(taskId)

.taskAssignee(assingee)

.singleResult();

if(task != null){

taskService.complete(taskId);

System.out.println(“完成任务”);

}

}

[](()3.流程变量




[](()3.1、什么是流程变量

流程变量在 activiti 中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和 activiti结合时少不了流程变量,流程变量就是 activiti 在管理工作流时根据管理需要而设置的变量。比如:在出差申请流程流转时如果出差天数大于 3 天则由总经理审核,否则由人事直接审核, 出差天数就可以设置为流程变量,在流程流转时使用。


注意:虽然流程变量中可以存储业务数据可以通过activiti的api查询流程变量从而实现 查询业务数据,但是不建议这样使用,因为业务数据查询由业务系统负责,activiti设置流程变量是为了流程执行需要而创建。



[](()3.2、流程变量类型

如果将 pojo 存储到流程变量中,必须实现序列化接口 serializable,为了防止由于新增字段无法反序列化,需要生成 serialVersionUID。

在这里插入图片描述



[](()3.3、流程变量作用域

流程变量的作用域可以是一个流程实例(processInstance),或一个任务(task),或一个执行实例

(execution)



[](()3.3.1、globa变量

流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例时,可以称为 global 变量

注意:

如: Global变量:userId(变量名)、zhangsan(变量值)

global 变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值。



[](()3.3.2、local变量

任务和执行实例仅仅是针对一个任务和一个执行实例范围,范围没有流程实例大, 称为 local 变量。Local 变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。Local 变量名也可以和 global 变量名相同,没有影响。



[](()3.4、流程变量的使用方法



[](()3.4.1、在属性上使用UEL表达式

可以在 assignee 处设置 UEL 表达式,表达式的值为任务的负责人,比如: ${assignee}, assignee 就是一个流程变量名称。

Activiti获取UEL表达式的值,即流程变量assignee的值 ,将assignee的值作为任务的负责人进行任务分配



[](()3.4.2、在连线上使用UEL表达式

可以在连线上设置UEL表达式,决定流程走向。比如:${price<10000} 。price就是一个流程变量名称,uel表达式结果类型为布尔类型。如果UEL表达式是true,要决定 流程执行走向。



[](()3.5 流程变量使用



[](()3.5.1 需求

​   员工创建出差申请单,由部门经理审核,部门经理申请通过后3天以下由财务直接申批,3天以上先由总经理审批,总经理审批通过后再由财务审批。

在这里插入图片描述



[](()3.5.2 流程定义

先通过UEL-value来设置负责人
在这里插入图片描述

然后在分支线上来设置条件

在这里插入图片描述

那么还可以通过对象参数命名,比如 evection.num:

在这里插入图片描述

另一根线对应的设置

在这里插入图片描述

在这里插入图片描述

然后可以将相关的资源文件拷贝到项目中,



[](()3.5.3 使用Global变量

接下来使用Global变量控制流程



[](()3.5.3.1 POJO创建

首先创建POJO对象

/**

  • 出差申请的POJO对象

*/

@Data

public class Evection {

private long id;

private String evectionName;

/**

  • 出差的天数

*/

private double num;

private Date beginDate;

private Date endDate;

private String destination;

private String reson;

}



[](()3.5.3.2 流程的部署

/**

  • 部署流程

*/

@Test

public void test01(){

// 1.获取ProcessEngine对象

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

// 2.获取RepositoryService进行部署操作

RepositoryService service = engine.getRepositoryService();

// 3.使用RepositoryService进行部署操作

Deployment deploy = service.createDeployment()

.addClasspathResource(“bpmn/evection-variable.bpmn”) // 添加bpmn资源

.addClasspathResource(“bpmn/evection-variable.png”) // 添加png资源

.name(“出差申请流程-流程变量”)

.deploy();// 部署流程

// 4.输出流程部署的信息

System.out.println(“流程部署的id:” + deploy.getId());

System.out.println(“流程部署的名称:” + deploy.getName());

}



[](()3.5.3.3 设置流程变量


[](()a.启动时设置流程变量

在启动流程时设置流程变量,变量的作用域是整个流程实例。

/**

  • 启动流程实例,设置流程变量

*/

@Test

public void test02(){

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

RuntimeService runtimeService = engine.getRuntimeService();

// 流程定义key

String key = “evection-variable”;

// 创建变量集合

Map<String,Object> variables = new HashMap<>();

// 创建出差对象 POJO

Evection evection = new Evection();

// 设置出差天数

evection.setNum(4d);

// 定义流程变量到集合中

variables.put(“evection”,evection);

// 设置assignee的取值

variables.put(“assignee0”,“张三1”);

variables.put(“assignee1”,“李四1”);

variables.put(“assignee2”,“王五1”);

variables.put(“assignee3”,“赵财务1”);

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, variables);

// 输出信息

System.out.println(“获取流程实例名称:”+processInstance.getName());

System.out.println(“流程定义ID:” + processInstance.getProcessDefinitionId());

}

完成任务

/**

  • 完成任务

*/

@Test

public void test03(){

String key = “evection-variable”;

String assignee = “李四1”;

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = engine.getTaskService();

Task task = taskService.createTaskQuery()

.processDefinitionKey(key)

.taskAssignee(assignee)

.singleResult();

if(task != null){

taskService.complete(task.getId());

System.out.println(“任务执行完成…”);

}

}

通过startProcessInstanceByKey方法设置流程变量的作用域是一个流程实例,流程变量使用Map存储,同一个流程实例map中的key相同,后者会覆盖前者



[](()b.任务办理时设置

在完成任务时设置流程变量,该流程变量只有在该任务完成后其它结点才可使用该变量,它的作用域是整个流程实例,如果设置的流程变量的key在流程实例中已存在相同的名字则后设置的变量替换前边设置的变量。

这里需要在创建出差单任务完成时设置流程变量

/**

  • 启动流程实例,设置流程变量

*/

@Test

public void test02(){

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

RuntimeService runtimeService = engine.getRuntimeService();

// 流程定义key

String key = “evection-variable”;

// 创建变量集合

Map<String,Object> variables = new HashMap<>();

// 设置assignee的取值

variables.put(“assignee0”,“张三1”);

variables.put(“assignee1”,“李四1”);

variables.put(“assignee2”,“王五1”);

variables.put(“assignee3”,“赵财务1”);

ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(key, variables);

// 输出信息

System.out.println(“获取流程实例名称:”+processInstance.getName());

System.out.println(“流程定义ID:” + processInstance.getProcessDefinitionId());

}

/**

  • 完成任务

*/

@Test

public void test03(){

String key = “evection-variable”;

String assignee = “李四1”;

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = engine.getTaskService();

Task task = taskService.createTaskQuery()

.processDefinitionKey(key)

.taskAssignee(assignee)

.singleResult();

Map<String,Object> variables = new HashMap<>();

// 创建出差对象 POJO

Evection evection = new Evection();

// 设置出差天数

evection.setNum(4d);

// 定义流程变量到集合中

variables.put(“evection”,evection);

if(task != null){

taskService.complete(task.getId(),variables);

System.out.println(“任务执行完成…”);

}

}

说明:

通过当前任务设置流程变量,需要指定当前任务id,如果当前执行的任务id不存在则抛出异常。

任务办理时也是通过map<key,value>设置流程变量,一次可以设置多个变量。



[](()c.当前流程实例设置

通过流程实例id设置全局变量,该流程实例必须未执行完成。

@Test

public void setGlobalVariableByExecutionId(){

// 当前流程实例执行 id,通常设置为当前执行的流程实例

String executionId=“2601”;

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

// 获取RuntimeService

RuntimeService runtimeService = processEngine.getRuntimeService();

// 创建出差pojo对象

Evection evection = new Evection();

// 设置天数

evection.setNum(3d);

// 通过流程实例 id设置流程变量

runtimeService.setVariable(executionId, “evection”, evection);

// 一次设置多个值

// runtimeService.setVariables(executionId, variables)

}

注意:

executionId必须当前未结束 流程实例的执行id,通常此id设置流程实例 的id。也可以通runtimeService.getVariable()获取流程变量。



[](()d.当前任务设置

@Test

public void setGlobalVariableByTaskId(){

//当前待办任务id

String taskId=“1404”;

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = processEngine.getTaskService();

Evection evection = new Evection();

evection.setNum(3);

//通过任务设置流程变量

taskService.setVariable(taskId, “evection”, evection);

//一次设置多个值

//taskService.setVariables(taskId, variables)

}

注意:

任务id必须是当前待办任务id,act_ru_task中存在。如果该任务已结束,会报错也可以通过taskService.getVariable()获取流程变量。



[](()3.5.4 设置local流程变量



[](()3.5.4.1、任务办理时设置

任务办理时设置local流程变量,当前运行的流程实例只能在该任务结束前使用,任务结束该变量无法在当前流程实例使用,可以通过查询历史任务查询。

/*

*处理任务时设置local流程变量

*/

@Test

public void completTask() {

//任务id

String taskId = “1404”;

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = processEngine.getTaskService();

// 定义流程变量

Map<String, Object> variables = new HashMap<String, Object>();

Evection evection = new Evection ();

evection.setNum(3d);

// 定义流程变量

Map<String, Object> variables = new HashMap<String, Object>();

// 变量名是holiday,变量值是holiday对象

variables.put(“evection”, evection);

// 设置local变量,作用域为该任务

taskService.setVariablesLocal(taskId, variables);

// 完成任务

taskService.complete(taskId);

}

​ 说明:

设置作用域为任务的local变量,每个任务可以设置同名的变量,互不影响。



[](()3.5.4.2、通过当前任务设置

@Test

public void setLocalVariableByTaskId(){

// 当前待办任务id

String taskId=“1404”;

// 获取processEngine

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = processEngine.getTaskService();

Evection evection = new Evection ();

evection.setNum(3d);

// 通过任务设置流程变量

taskService.setVariableLocal(taskId, “evection”, evection);

// 一次设置多个值

//taskService.setVariablesLocal(taskId, variables)

}

注意:

任务id必须是当前待办任务id,act_ru_task中存在。



[](()3.5.4.3、 Local变量测试1

如果上边例子中设置global变量改为设置local变量是否可行?为什么?

Local变量在任务结束后无法在当前流程实例执行中使用,如果后续的流程执行需要用到此变量则会报错。



[](()3.5.4.4、 Local变量测试2

在部门经理审核、总经理审核、财务审核时设置local变量,可通过historyService查询每个历史任务时将流程变量的值也查询出来。

代码如下:

// 创建历史任务查询对象

HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();

// 查询结果包括 local变量

historicTaskInstanceQuery.includeTaskLocalVariables();

for (HistoricTaskInstance historicTaskInstance : list) {

System.out.println(“==============================”);

System.out.println(“任务id:” + historicTaskInstance.getId());

System.out.println(“任务名称:” + historicTaskInstance.getName());

System.out.println(“任务负责人:” + historicTaskInstance.getAssignee());

System.out.println(“任务local变量:”+ historicTaskInstance.getTaskLocalVariables());

}

注意:查询历史流程变量,特别是查询pojo变量需要经过反序列化,不推荐使用。

[](()4.组任务




[](()4.1、需求

在流程定义中在任务结点的 assignee 固定设置任务负责人,在流程定义时将参与者固定设置在.bpmn 文件中,如果临时任务负责人变更则需要修改流程定义,系统可扩展性差。

针对这种情况可以给任务设置多个候选人,可以从候选人中选择参与者来完成任务。



[](()4.2、设置任务候选人

在流程图中任务节点的配置中设置 candidate-users(候选人),多个候选人之间用逗号分开。

在这里插入图片描述

查看bpmn文件

我们可以看到部门经理的审核人已经设置为 lisi,wangwu 这样的一组候选人,可以使用activiti:candiateUsers=”用户 1,用户 2,用户 3”的这种方式来实现设置一组候选人



[](()4.3、组任务



[](()4.3.1、组任务办理流程



[](()a、查询组任务

指定候选人,查询该候选人当前的待办任务。候选人不能立即办理任务。



[](()b、拾取(claim)任务

该组任务的所有候选人都能拾取。将候选人的组任务,变成个人任务。原来候选人就变成了该任务的负责人。如果拾取后不想办理该任务?需要将已经拾取的个人任务归还到组里边,将个人任务变成了组任务。



[](()c、查询个人任务

查询方式同个人任务部分,根据assignee查询用户负责的个人任务。



[](()d、办理个人任务



[](()4.3.2、 查询组任务

根据候选人查询组任务

/**

  • 查询组任务

*/

@Test

public void test03(){

String key = “evection1”;

String candidateUser = “lisi”;

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = engine.getTaskService();

List list = taskService.createTaskQuery()

.processDefinitionKey(key)

.taskCandidateUser(candidateUser)

.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());

}

}



[](()4.3.3 、 拾取组任务

候选人员拾取组任务后该任务变为自己的个人任务。

/**

  • 候选人 拾取任务

*/

@Test

public void test04(){

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = engine.getTaskService();

String taskId = “72505”;

// 候选人

String userId = “lisi”;

// 拾取任务

Task task = taskService.createTaskQuery()

.taskId(taskId)

.taskCandidateUser(userId) // 根据候选人查询

.singleResult();

if(task != null){

// 可以拾取任务

taskService.claim(taskId,userId);

System.out.println(“拾取成功”);

}

}



[](()4.3.4、 查询个人待办任务

查询方式同个人任务查询

@Test

public void test03(){

String key = “evection1”;

String candidateUser = “lisi”;

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = engine.getTaskService();

List list = taskService.createTaskQuery()

.processDefinitionKey(key)

//.taskCandidateUser(candidateUser)

//.taskCandidateOrAssigned(candidateUser)

.taskAssignee(candidateUser)

.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());

}

}


《一线大厂Java面试真题解析+Java核心总结学习笔记+最新全套讲解视频+实战项目源码》开源


Java优秀开源项目:


  • ali1024.coding.net/public/P7/Java/git



最后


面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典

  • Java核心知识整理

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

Java核心知识

  • Spring全家桶(实战系列)

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

  • 其他电子书资料

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多


Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。


以下是我私藏的面试题库:

2020年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

@Test

public void test03(){

String key = “evection1”;

String candidateUser = “lisi”;

ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();

TaskService taskService = engine.getTaskService();

List list = taskService.createTaskQuery()

.processDefinitionKey(key)

//.taskCandidateUser(candidateUser)

//.taskCandidateOrAssigned(candidateUser)

.taskAssignee(candidateUser)

.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());

}

}


《一线大厂Java面试真题解析+Java核心总结学习笔记+最新全套讲解视频+实战项目源码》开源


Java优秀开源项目:


  • ali1024.coding.net/public/P7/Java/git



最后


面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典

  • Java核心知识整理

[外链图片转存中…(img-YeAzlkeK-1649661139964)]

Java核心知识

  • Spring全家桶(实战系列)

[外链图片转存中…(img-kkIOOTmu-1649661139965)]

  • 其他电子书资料

[外链图片转存中…(img-gDifJRBu-1649661139965)]


Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。


以下是我私藏的面试题库:

[外链图片转存中…(img-0WtOzKWv-1649661139965)]



版权声明:本文为m0_52267935原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。