首页 » Web前端 » phpunknownproperty技巧_2021全网最全Activiti7之核心进阶内容实战内容

phpunknownproperty技巧_2021全网最全Activiti7之核心进阶内容实战内容

访客 2024-12-07 0

扫一扫用手机浏览

文章目录 [+]

全网最详细Activiti系列文章,强烈建议收藏加关注哦!

Activiti进阶篇1.流程实例1.1 什么是流程实例

  流程实例(ProcessInstance)代表流程定义的实行实例,一个流程实例包括了所有的运行节点,我们可以利用这个工具来理解当前流程实例的进度等信息  例如:用户或者程序安装流程定义的内容发起了一个流程,这个便是一个流程实例

phpunknownproperty技巧_2021全网最全Activiti7之核心进阶内容实战内容

在这里插入图片描述

phpunknownproperty技巧_2021全网最全Activiti7之核心进阶内容实战内容
(图片来自网络侵删)
1.2 业务管理

  流程定义支配在Activiti后,我们就可以在系统中通过Activiti去管理流程的实行,但是如果我们要将我们的流程实例和业务数据关联,这时我们须要利用到Activiti中预留的BusinessKey(业务标识)来关联

在这里插入图片描述

实当代码: / 启动流程实例,添加businessKey/@Testpublic void test01(){// 1.获取ProcessEngine工具ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();// 2.获取RuntimeService工具RuntimeService runtimeService = processEngine.getRuntimeService();// 3.启动流程实例ProcessInstance instance = runtimeService.startProcessInstanceByKey("evection", "1001");// 4.输出processInstance干系属性System.out.println("businessKey = "+instance.getBusinessKey());}

在这里插入图片描述

1.3 流程实例的挂起和激活

  在实际场景中可能由于流程变更须要将当前运行的流程停息而不是删除,流程停息后将不能连续实行。

1.3.1 全部流程挂起

  操作流程的定义为挂起状态,该流程定义下边所有的流程实例全部停息。

流程定义为挂起状态,该流程定义将不许可启动新的流程实例,同时该流程定义下的所有的流程实例都将全部挂起停息实行。

/ 全部流程挂起实例与激活 / @Test public void test02(){ // 1.获取ProcessEngine工具 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); // 2.获取RepositoryService工具 RepositoryService repositoryService = engine.getRepositoryService(); // 3.查询流程定义的工具 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("evection") .singleResult(); // 4.获取当前流程定义的状态 boolean suspended = processDefinition.isSuspended(); String id = processDefinition.getId(); // 5.如果挂起就激活,如果激活就挂起 if(suspended){ // 表示当前定义的流程状态是 挂起的 repositoryService.activateProcessDefinitionById( id // 流程定义的id ,true // 是否激活 ,null // 激活韶光 ); System.out.println("流程定义:" + id + ",已激活"); }else{ // 非挂起状态,激活状态 那么须要挂起流程定义 repositoryService.suspendProcessDefinitionById( id // 流程id ,true // 是否挂起 ,null // 挂起韶光 ); System.out.println("流程定义:" + id + ",已挂起"); } }

  挂起流程定义后,对付的实例工具中的状态会修正为2

在这里插入图片描述

  然后再去操为难刁难于的流程实例会抛非常信息

在这里插入图片描述

  我们再将挂起的流程转变为激活状态,对付的状态值会从2更新为1

在这里插入图片描述

  然后便是业务流程可以正常处理了

1.3.2 单个实例挂起

  操作流程实例工具,针对单个流程实行挂起操作,某个流程实例挂起则此流程不再连续实行,当前流程定义的其他流程实例是不受滋扰的。
完成该流程实例确当前任务会抛非常

/ 单个流程实例挂起与激活 / @Test public void test03(){ // 1.获取ProcessEngine工具 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); // 2.获取RuntimeService RuntimeService runtimeService = engine.getRuntimeService(); // 3.获取流程实例工具 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId("25001") .singleResult(); // 4.获取干系的状态操作 boolean suspended = processInstance.isSuspended(); String id = processInstance.getId(); if(suspended){ // 挂起--》激活 runtimeService.activateProcessInstanceById(id); System.out.println("流程定义:" + id + ",已激活"); }else{ // 激活--》挂起 runtimeService.suspendProcessInstanceById(id); System.out.println("流程定义:" + id + ",已挂起"); } }

  然后我们可以在数据库中查看到状态的更新

在这里插入图片描述

2. 个人任务2.1 分配任务任务人2.1.1 固定分配

  在进行业务流程建模的时候指定固定的任务卖力人:

在这里插入图片描述

  在Properties视图中,填写Assiginee项为任务卖力人

2.1.2 表达式分配

  在Activiti中支持利用UEL表达式,UEL表达式是Java EE6 规范的一部分, UEL(Unified Expression Language) 即 统一表达式语音, Activiti支持两种UEL表达式: UEL-value 和UEL-method

UEL-value

在这里插入图片描述

  在assignee中利用流程变量处理

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  然后我们可以来操作

  首先我们须要将定义的流程支配到Activiti数据库中

/ 先将新定义的流程支配到Activiti中数据库中 / @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-uel.bpmn") // 添加bpmn资源 .addClasspathResource("bpmn/evection-uel.png") // 添加png资源 .name("出差申请流程-UEL") .deploy();// 支配流程 // 4.输出流程支配的信息 System.out.println("流程支配的id:" + deploy.getId()); System.out.println("流程支配的名称:" + deploy.getName()); }

  支配成功后我们须要启动一个新的流程实例,然后在流程实例创建的实在关联UEL表达式

/ 创建一个流程实例 给流程定义中的 UEL表达式赋值 / @Test public void test02(){ // 获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // 获取RuntimeService工具 RuntimeService runtimeService = processEngine.getRuntimeService(); // 设置 assignee 的取值, Map<String,Object> map = new HashMap<>(); map.put("assignee0","张三"); map.put("assignee1","李四"); map.put("assignee2","王五"); map.put("assignee3","赵财务"); // 创建流程实例 runtimeService.startProcessInstanceByKey("evection-uel",map); }

  启动成功后我们在 act_ru_variable中可以看到UEL表达式对应的赋值信息

在这里插入图片描述

  UEL-method

在这里插入图片描述

  userBean 是 spring 容器中的一个 bean,表示调用该 bean 的 getUserId()方法。

UEL-method 与 UEL-value 结合

再比如:

不能识别此Latex公式:{ldapService.findManagerForEmployee(emp)}ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中。
其它  表达式支持解析根本类型、 bean、 list、 array 和 map,也可作为条件判断。
  如下:  

{order.price > 100 && order.price < 250}

2.1.3 监听器分配

  可以利用监听器来完成很多Activiti的流程业务。
我们在此处利用监听器来完成卖力人的指定,那么我们在流程设计的时候就不须要指定assigneeEvent选项

在这里插入图片描述

create:任务创建后触发assignment:任务分配后触发Delete:任务完成后触发All:所有事宜都触发

自定义的监听器

import org.activiti.engine.delegate.DelegateTask;import org.activiti.engine.delegate.TaskListener;public class MyTaskListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { if("创建请假单".equals(delegateTask.getName()) && "create".equals(delegateTask.getEventName())){ // 指界说务的卖力人 delegateTask.setAssignee("张三-Listener"); } }}

测试代码

/ 先将新定义的流程支配到Activiti中数据库中 /@Testpublic void test01(){ // 1.获取ProcessEngine工具 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); // 2.获取RepositoryService进行支配操作 RepositoryService service = engine.getRepositoryService(); // 3.利用RepositoryService进行支配操作 Deployment deploy = service.createDeployment() .addClasspathResource("bpmn/evection-listener.bpmn") // 添加bpmn资源 .addClasspathResource("bpmn/evection-listener.png") // 添加png资源 .name("出差申请流程-UEL") .deploy();// 支配流程 // 4.输出流程支配的信息 System.out.println("流程支配的id:" + deploy.getId()); System.out.println("流程支配的名称:" + deploy.getName());}/ 创建一个流程实例 给流程定义中的 UEL表达式赋值 /@Testpublic void test02(){ // 获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // 获取RuntimeService工具 RuntimeService runtimeService = processEngine.getRuntimeService(); // 创建流程实例 runtimeService.startProcessInstanceByKey("evection-listener");}

在这里插入图片描述

在这里插入图片描述

2.2 查询任务查询任务卖力人的待办任务

代码如下:

// 查询当前个人待实行的任务@Testpublic void findPersonalTaskList() { // 流程定义key String processDefinitionKey = "myEvection1"; // 任务卖力人 String assignee = "张三"; // 获取TaskService TaskService taskService = processEngine.getTaskService(); List<Task> 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 表达式,表达式的值为任务的卖力人,比如:

不能识别此Latex公式:{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工具 /@Datapublic 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设置流程变量,一次可以设置多个变量。

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流程变量/@Testpublic 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、通过当前任务设置

@Testpublic 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文件

<userTask activiti:candidateUsers="lisi,wangwu" activiti:exclusive="true" id="_3" name="经理审批"/>

  我们可以看到部门经理的审核人已经设置为 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<Task> 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<Task> 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()); } }4.3.5、 办理个人任务

  同个人任务办理

/ 完成个人任务 / @Test public void test05(){ String taskId = "72505"; ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); taskService.complete(taskId); System.out.println("完成任务:" + taskId); }4.3.6、 归还组任务

   如果个人不想办理该组任务,可以归还组任务,归还后该用户不再是该任务的卖力人

/ 归还任务 / @Test public void test06(){ ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); String taskId = "75002"; String userId= "zhangsan"; Task task = taskService.createTaskQuery() .taskId(taskId) .taskAssignee(userId) .singleResult(); if(task != null){ // 如果设置为null,归还组任务,任务没有卖力人 taskService.setAssignee(taskId,null); } }4,3,7 任务交卸

  任务卖力人将任务交给其他卖力人来处理

/ 任务交卸 / @Test public void test07(){ ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); String taskId = "75002"; String userId= "zhangsan"; Task task = taskService.createTaskQuery() .taskId(taskId) .taskAssignee(userId) .singleResult(); if(task != null){ // 设置该任务的新的卖力人 taskService.setAssignee(taskId,"赵六"); } }4.3.8、 数据库表操作

  查询当前任务实行表

SELECT FROM act_ru_task

  任务实行表,记录当前实行的任务,由于该任务当前是组任务,所有assignee为空,当拾取任务后该字段便是拾取用户的id,查询任务参与者

SELECT FROM act_ru_identitylink

  任务参与者,记录当前参考任务用户或组,当前任务如果设置了候选人,会向该表插入候选人记录,有几个候选就插入几个与act_ru_identitylink对应的还有一张历史表act_hi_identitylink,向act_ru_identitylink插入记录的同时也会向历史表插入记录。
任务完成

5.网关

  网关用来掌握流程的流向

5.1 排他网关ExclusiveGateway5.1.1 什么是排他网关:

  排他网关,用来在流程中实现决策。
当流程实行到这个网关,所有分支都会判断条件是否为true,如果为true则实行该分支,

把稳:排他网关只会选择一个为true的分支实行。
如果有两个分支条件都为true,排他网关会选择id值较小的一条分支去实行。

为什么要用排他网关?

  不用排他网关也可以实现分支,如:在连线的condition条件上设置分支条件。
在连线设置condition条件的缺陷:如果条件都不知足,流程就结束了(是非常结束)。
如果 利用排他网关决定分支的走向,如下:

在这里插入图片描述

  如果从网关出去的线所有条件都不知足则系统抛出非常。

org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway 'exclusivegateway1' could be selected for continuing the process at org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivityBehavior.java:85)5.1.2 流程定义

  排他网关图标,红框内:

在这里插入图片描述

5.1.3 测试

  在部门经理审核后,走排他网关,从排他网关出来的分支有两条,一条是判断出差天数是否大于3天,另一条是判断出差天数是否小于即是3天。
设置分支条件时,如果所有分支条件都不是true,报错:

org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway 'exclusivegateway1' could be selected for continuing the process at org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivityBehavior.java:85)5.2 并行网关ParallelGateway5.2.1 什么是并行网关

  并行网关许可将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进入和外出顺序流的:

l fork分支:

  并行后的所有外出顺序流,为每个顺序流都创建一个并发分支。

l join汇聚:

  所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达往后, 流程就会通过汇聚网关。
把稳,如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。
这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。

与其他网关的紧张差异是,并行网关不会解析条件。
纵然顺序流中定义了条件,也会被忽略。

例子:

在这里插入图片描述

解释:

  技能经理和项目经理是两个execution分支,在act_ru_execution表有两条记录分别是技能经理和项目经理,act_ru_execution还有一条记录表示该流程实例。
待技能经理和项目经理任务全部完成,在汇聚点汇聚,通过parallelGateway并行网关。
并行网关在业务运用中常用于会签任务,会签任务即多个参与者共同办理的任务。

5.2.2 流程定义

  并行网关图标,红框内:

在这里插入图片描述

5.2.3 测试

  当实行到并行网关数据库跟踪如下:当前任务表:SELECT FROM act_ru_task

在这里插入图片描述

上图中:有两个任务当前实行。
查询流程实例实行表:SELECT FROM act_ru_execution

在这里插入图片描述

上图中,解释当前流程实例有多个分支(两个)在运行。

对并行任务的实行:并行任务实行不分前后,由任务的卖力人去实行即可。
实行技能经理任务后,查询当前任务表 SELECT FROM act_ru_task

在这里插入图片描述

已完成的技能经理任务在当前任务表act_ru_task_已被删除。
在流程实例实行表:SELECT FROM act_ru_execution有中多个分支存在且有并行网关的汇聚结点。

在这里插入图片描述

有并行网关的汇聚结点:解释有一个分支已经到汇聚,等待其它的分支到达。
当所有分支任务都完成,都到达汇聚结点后:流程实例实行表:SELECT FROM act_ru_execution,实行流程实例已经变为总经理审批,解释流程实行已经通过并行网关

在这里插入图片描述

总结:所有分支到达汇聚结点,并行网关实行完成。

5.3 包含网关InclusiveGateway5.3.1 什么是包含网关

  包含网关可以看做是排他网关和并行网关的结合体。
和排他网关一样,你可以在外出顺序流上定义条件,包含网关会解析它们。
但是紧张的差异是包含网关可以选择多于一条顺序流,这和并行网关一样。
  包含网关的功能是基于进入和外出顺序流的:

l 分支:

  所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行办法连续实行, 会为每个顺序流创建一个分支。

l 汇聚:

  所有并行分支到达包含网关,会进入等待状态, 直到每个包含流程token的进入顺序流的分支都到达。
这是与并行网关的最大不同。
换句话说,包含网关只会等待当选中实行了的进入顺序流。
在汇聚之后,流程会穿过包含网关连续实行。

5.3.2 流程定义:

  出差申请大于即是3天须要由项目经理审批,小于3天由技能经理审批,出差申请必须经由人事经理审批。
包含网关图标,红框内:

在这里插入图片描述

定义流程:

在这里插入图片描述

把稳:通过包含网关的每个分支的连线上设置condition条件。

5.3.3 测试

  如果包含网关设置的条件中,流程变量不存在,报错;

org.activiti.engine.ActivitiException: Unknown property used in expression: ${evection.num>=3}

  须要在流程启动时设置流程变量evection.num。

1)、当流程实行到第一个包含网关后,会根据条件判断,当前要走哪几个分支:

  流程实例实行表:SELECT FROM act_ru_execution

在这里插入图片描述

第一条记录:包含网关分支。

后两条记录代表两个要实行的分支:ACT_ID = "_13" 代表 项目经理神品ACT_ID = "_5" 代表 人事经理审批当前任务表:ACT_RU_TASK

在这里插入图片描述

上图中,项目经理审批、人事经理审批 都是当前的任务,在并行实行。
如果有一个分支实行先走到汇聚结点的分支,要等待其它实行分支走到汇聚。

2)、先实行项目经理审批,然后查询当前任务表:ACT_RU_TASK

在这里插入图片描述

当前任务还有人事经理审批须要处理。
流程实例实行表:SELECT FROM act_ru_execution

在这里插入图片描述

  创造人事经理的分支还存在,而项目经理分支已经走到ACT_ID = _18的节点。
而ACT_ID=__18便是第二个包含网关这时,由于有2个分支要实行,包含网关会等所有分支走到汇聚才能实行完成。

3)、实行人事经理审批然后查询当前任务表:ACT_RU_TASK

在这里插入图片描述

  当前任务表已经不是人事经理审批了,解释人事经理审批已经完成。
流程实例实行表:SELECT FROM act_ru_execution

在这里插入图片描述

包含网关实行完成,分支和汇聚就从act_ru_execution删除。

小结:在分支时,须要判断条件,符合条件的分支,将会实行,符合条件的分支终极才进行汇聚。

5.4 事宜网关EventGateway

  事宜网关许可根据事宜判断流向。
网关的每个外出顺序流都要连接到一个中间捕获事宜。
当流程到达一个基于事宜网关,网关会进入等待状态:会停息实行。
与此同时,会为每个外出顺序流创建相对的事宜订阅。

  事宜网关的外出顺序流和普通顺序流不同,这些顺序流不会真的"实行", 相反它们让流程引擎去决定实行到事宜网关的流程须要订阅哪些事宜。
要考虑以下条件:

事宜网关必须有两条或以上外出顺序流;事宜网关后,只能利用intermediateCatchEvent类型(activiti不支持基于事宜网关后连接ReceiveTask)连接到事宜网关的中间捕获事宜必须只有一个入口顺序流。
5.4.1流程定义

事宜网关图标,红框内

在这里插入图片描述

intermediateCatchEvent:

在这里插入图片描述

intermediateCatchEvent支持的事宜类型:Message Event: 事宜Singal Event: 旗子暗记事宜Timer Event: 定时事宜

在这里插入图片描述

利用事宜网关定义流程:

在这里插入图片描述

~好了进阶篇的内容就给大家先容到这儿了,如果觉得有帮助欢迎点赞关注加收藏哦 V_V

标签:

相关文章

田睿php技巧_智同志合赋能数据新基建

“2021聪慧数据中央峰会”是往届“企业级数据中央论坛”品牌会议的延续和升级。通过对数据中央行业发展趋势的潜心研究,我们认为,“聪...

Web前端 2024-12-08 阅读0 评论0