工作流学习日志 -(Activiti7进阶)
2021/4/13 10:59:18
本文主要是介绍工作流学习日志 -(Activiti7进阶),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
工作流学习日志 -(Activiti7进阶)
文章目录
- 工作流学习日志 -(Activiti7进阶)
- 前言
- 一、流程实例
- 1. 添加业务标识(BusinessKey)
- 2. 查询流程实例
- 3. 挂起、激活流程实例
- ①. 全部流程实例挂起、激活
- ②. 单个流程实例挂起、激活
- 二、个人任务
- 1. 分配任务负责人
- ①. 固定分配方式
- ②. 表达式分配
- ③. 监听器分配
- 2. 查询任务
- 3. 办理任务
- 三. 流程变量
- 1. 概念
- 2. 流程变量类型
- 3. 流程变量作用域
- ①. global变量
- ②. local变量
- 4. 流程变量的使用方法
- ①. 在属性上使用UEL表达式
- ②. 在连线上使用UEL表达式
- ③. 设置global变量
- 四. 组任务
- 1. 需求
- 2. 设置任务候选人
- 3. 组任务
- ①. 查询组任务
- ②. 拾取(claim)任务
- ③. 查询个人任务
- ④. 办理个人任务
- 五. 网关
- 1. 排他网关ExclusiveGateway
- ①. 概念
- ②. 用法
- 2. 并行网关ParallelGateway
- 3. 包含网关InclusiveGetaway
- 总结
前言
开发OA人力资源管理系统时在人员调动时、请假审批等需要使用到工作流,以此作为学习契机。
工作流学习日志(基础-概念、基本api使用)
一、流程实例
流程实例(ProcessInstance)通过流程定义(ProcessDefinition)创建,代表了流程定义的实例。
1. 添加业务标识(BusinessKey)
BusinessKey:业务标识,通常是业务表的主见id,业务标识和流程实例一一对应。存储业务标识就是根据业务标识来关联查询业务系统的数据。其中的业务和流程是分开的,activiti主要是控制流程,而不是控制所有的的业务,所以需要使用有一张其他的表表示业务,最后可以进行关联。
例如:出差流程是一个流程实例,可以将出差单(业务)id作为BusinessKey存储到activiti中。将来查询activiti流程实例的信息就可以获取到对应的出差单(业务)id从而关联到业务系统数据库中的出差单信息。
添加businessKey并启动流程实例代码:
//1.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取RuntimeService RuntimeService runtimeService = processEngine.getRuntimeService(); //3.添加businessKey(可以指某用户Id,开启一个新的工作流程 例如为1001) ProcessInstance processInstance = runtimeService .startProcessInstanceByKey("myBusinessTrip", "1001"); System.out.println("流程业务名称="+processInstance.getBusinessKey());
添加成功后可以在Activiti数据库act_ru_execution中查看到存储的businessKey。
查询关联的businessKey:
// 获取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. 查询流程实例
流程在运行的过程中可以查询流程实例的状态,当前运行节点等信息
// 流程定义key String processDefinitionKey = "evection"; ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); // 获取RunTimeService RuntimeService runtimeService = processEngine.getRuntimeService(); List<ProcessInstance> list = runtimeService .createProcessInstanceQuery() .processDefinitionKey(processDefinitionKey)// .list(); for (ProcessInstance processInstance : list) { System.out.println("----------------------------"); System.out.println("流程实例id:" + processInstance.getProcessInstanceId()); System.out.println("所属流程定义id:" + processInstance.getProcessDefinitionId()); System.out.println("是否执行完成:" + processInstance.isEnded()); System.out.println("是否暂停:" + processInstance.isSuspended()); System.out.println("当前活动标识:" + processInstance.getActivityId()); }
3. 挂起、激活流程实例
某些情况下流程变更需要当前运行的流程暂停而不是直接删除,那么可以将流程进行挂起,流程挂起后将不能继续执行流程,需要激活后才能继续执行。
例如:当审批员有变更的时候,那么审批的流程需要进行暂停,待审批员变更完成后才能继续进行执行;或者在非工作日时不能进行流程执行操作。
①. 全部流程实例挂起、激活
- 将整个流程定义为挂起状态,该流程定义下的所有流程实例将全部挂起。
- 流程定义为挂起状态后,该流程定义将不允许启动新的流程实例,同时该流程定义定义下的所有流程实例将全部挂起暂停执行。
代码如下:
//1.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取RepositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); //3.获取到流程定义的查询对象 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("myBusinessTrip") .singleResult(); //4.查询processDefinition流程定义的状态 boolean suspended = processDefinition.isSuspended(); //5.如果挂起,那么激活流程定义 String definitionId = processDefinition.getId(); if (suspended) { //参数1:流程定义id,参数2:流程是否激活,参数3:流程激活时间 repositoryService.activateProcessDefinitionById(definitionId,true,null); System.out.println("流程定义id为:"+definitionId+"激活成功"); } else{ //6.如果正在活动,那么将流程定义挂起 //参数1:流程定义id,参数2:流程是否挂起,参数3:流程挂起时间 repositoryService.suspendProcessDefinitionById(definitionId,true,null); System.out.println("流程定义id为:"+definitionId+"挂起成功"); }
②. 单个流程实例挂起、激活
操作流程实例的对象,针对单个流程执行挂起操作,某个流程实例挂起则此流程不再继续进行执行,完成该流程实例的当前任务将报异常。
代码如下:
//1.获取processEngine 引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取runtimeService RuntimeService runtimeService = processEngine.getRuntimeService(); //3.根据processInstanceId获取指定的流程实例查询对象 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId("2501") .singleResult(); //4.根据processInstance流程实例获取其状态 boolean suspended = processInstance.isSuspended(); //5.如果为挂起状态,那么激活 String instanceId = processInstance.getId(); if(suspended){ runtimeService.activateProcessInstanceById(instanceId); System.out.println("流程实例对象Id="+instanceId+",已经激活"); }else { //6.如果流程实例的状态为激活状态,那么将其挂起 runtimeService.suspendProcessInstanceById(instanceId); System.out.println("流程实例对象Id="+instanceId+",已经挂起"); }
- 测试如果任务实例被挂起之后那么是否可以完成任务
- 如果任务激活状态:那么执行成功
- 如果为挂起状态:抛出异常Cannot complete a suspended task
//1.获取流程引擎processEngine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取对应的taskService TaskService taskService = processEngine.getTaskService(); //3.根据taskService获取对应的流程任务查询 Task task = taskService.createTaskQuery() .processInstanceId("2501")//根据流程实例id进行查询 .taskAssignee("lisi") .singleResult(); System.out.println("流程实例id="+task.getProcessInstanceId()); System.out.println("任务Id="+task.getId()); System.out.println("任务负责人="+task.getAssignee()); System.out.println("任务名称="+task.getName()); //4.根据taskId完成对应的任务 taskService.complete(task.getId()); }
二、个人任务
1. 分配任务负责人
①. 固定分配方式
直接在BPMN editor中将property为Assignee的值value设置为固定值,例:张三
②. 表达式分配
表达式分配可以解决固定分配情况下的assignee无法动态获取值的问题。
UEL表达式:
Activiti使用UEL表达式,UEL是java EE6规范的一部分,UEL(Unified Expression Language)即统一表达式语言,activiti支持两个UEL表达式:UEL-value和UEL-method。
1)UEL-value:
可以直接设置一个变量assignee0,该变量为activiti的一个流程变量。
也可以通过调用某个类中的属性获取值,例如user是activiti中一个流程变量,user.assignee表示通过调用user的getter方法获取值。
2)UEL-method方式
UserBean是spring容器中的一个bean,表示调用该bean的getUserId()方法。
3)UEL-method与UEL-value结合
再比如: ${ldapService.findManagerForEmployee(emp)} ldapService 是 spring 容器的一个 bean, findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti 流程变量, emp 作为参数传到
ldapService.findManagerForEmployee 方法中。
4)其他
表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。 如下: ${order.price > 100 && order.price < 250}
在启动流程实例时设置流程变量,如下:
//1.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取runtimeService RuntimeService runtimeService = processEngine.getRuntimeService(); //3.启动定义的流程,startProcessInstanceByKey两参数,一:流程实例的key,二:流程中定义的负责人名称使用map进行封装 //使用map封装负责人的值,可以在act_ru_variable数据表中查看设置的map值 Map map = new HashMap(); map.put("assignee0","张三"); map.put("assignee1","李四"); map.put("assignee2","王五"); map.put("assignee3","赵六"); runtimeService.startProcessInstanceByKey("myProcess_1",map); //4.输出 System.out.println("流程启动成功="+processEngine.getName());
执行成功后可以在数据库act_ru_variable表中看到刚才map中的数据
注:由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如: 某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在 流程变量中存在,否则 activiti 异常。
③. 监听器分配
Activiti中也有内置的监听器可以用来完成流程中的业务。可以使用任务监听器(Task Listener)指定负责人,那么在流程设计时可以不需要指定assignee。任务监听器是发生对应的任务相关事件时执行自定义java逻辑或表达式。
Event事件中包含了4个触发事件:
- create:任务创建后触发
- Assignment:任务分配后触发
- Delete:任务完成后触发
- ALL:所有事件发生都触发
代码如下:(定义任务监听类必须实现org.activiti.engine.delegate.TaskListener接口)
public class TestListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { //判断 if("创建申请".equals(delegateTask.getName()) && "create".equals(delegateTask.getEventName())){ delegateTask.setAssignee("张三"); } } }
注:使用监听器分配的方式,按照监听事件去执行监听类的notify方法,如果不能正常执行也会影响任务的执行。
2. 查询任务
查询任务负责人的待办任务,代码如下:
//选择负责人 String assignee = "zhangsan"; //获取到processEngine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //获取到taskService TaskService taskService = processEngine.getTaskService(); //使用TaskService根据流程的key和任务负责人查询任务 List<Task> list = taskService.createTaskQuery() .processDefinitionKey("myBusinessTrip")//流程的key .taskAssignee(assignee)//查询该负责人的任务 .list(); //遍历获取任务内容 for (Task task : list) { System.out.println("流程实例:"+task.getProcessInstanceId()); System.out.println("任务id:"+task.getId()); System.out.println("任务负责人:"+task.getAssignee()); System.out.println("任务名称:"+task.getName()); }
代码如下(示例):
data = pd.read_csv( 'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv') print(data.head())
3. 办理任务
注:实际应用中,完成任务前需要检验任务的负责人是否具有该任务的办理权限
String assignee = "zhangsan"; //1.创建processEngine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取到TaskService TaskService taskService = processEngine.getTaskService(); //完成任务前,需要检验该负责人是否可以完成当前任务 //检验方法:根据任务的id和任务负责人查询当前任务,如果查到该用户有权限,那么就完成。 //3.使用TaskService中的方法(使用任务id)完成任务 //taskService.complete("2505"); //4.根据流程的key以及负责人名称获取对应的任务id,动态进行完成任务 Task task = taskService.createTaskQuery() .processDefinitionKey("myBusinessTrip")//流程的key .taskAssignee(assignee)//任务负责人名称 .singleResult();//获取单个task任务 System.out.println("任务的id="+task.getProcessDefinitionId()); System.out.println("任务id="+task.getId()); System.out.println("任务的名称="+task.getName()); System.out.println("任务的负责人="+task.getAssignee()); //5.动态获取任务id完成任务 taskService.complete(task.getId());
三. 流程变量
1. 概念
流程变量的activiti中是一个非常重要的角色,流程运转有时需要靠流程变量,业务系统和activiti结合时少不了流程变量,流程变量就是activiti在管理工作流时根据管理需要而设置的变量。比如:在出差申请流程流转时如果出差天数大于3天那么由总经理审核,否则由部门经理进行审核,在这里的出差天数就可以设置为流程变量,在流程运转时使用。
注:流程变量中可以存储业务数据,可以通过activiti的api查询流程变量从而实现查询业务流程,单一一般不这样做,因为业务数据查询由业务系统负责,activiti设置流程变量是为了流程执行需要而创建。
2. 流程变量类型
注:如果需要将pojo存储在流程变量中,那么必须实现序列化接口serializable。为了防止由于新增字段无法反序列化,需要生成serialVersionUID。
类型名称:
- string
- integer
- short
- long
- double
- Boolean
- date
- binary
- serializable
3. 流程变量作用域
流程变量作用域可以是一个流程实例(processInstance)、任务(task)、执行实例(execution)
①. global变量
流程变量的默认作用域是流程实例。当一个流程变量的作用域为流程实例时,可以称为 global 变量
注:
如: Global变量:userId(变量名)、zhangsan(变量值)
global 变量中变量名不允许重复,设置相同名称的变量,后设置的值会覆盖前设置的变量值。
②. local变量
任务和执行实例仅仅是针对一个任务和一个执行实例范围,范围没有流程实例大, 称为 local 变量。
Local 变量由于在不同的任务或不同的执行实例中,作用域互不影响,变量名可以相同没有影响。Local 变量名也可以和 global 变量名相同,没有影响。
4. 流程变量的使用方法
①. 在属性上使用UEL表达式
在assignee设置UEL表达式设置为任务的负责人
②. 在连线上使用UEL表达式
在连线上设置UEL表达式,可以决定流程的走向,UEL表达式结果为布尔类型。如图:
③. 设置global变量
通过设置global变量控制流程走向
在部门经理审核前设置流程变量,变量值为出差单信息(包括出差天数),部门经理审核后可以根据流程变量的值决定流程走向。
在设置流程变量时,可以在启动流程时设置,也可以在任务办理时设置
创建POJO对象:
/** * 流程封装的业务类 * 出差申请pojo */ public class BusinessTrip implements Serializable { /** * 主键id */ private Long id; /** * 出差申请单名称 */ private String businessName; /** * 出差天数 */ private Double num; /** * 预计开始时间 */ private Date beginDate; /** * 预计结束时间 */ private Date endDate; /** * 目的地 */ private String destination; /** * 出差事由 */ private String reason; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getBusinessName() { return businessName; } public void setBusinessName(String businessName) { this.businessName = businessName; } public Double getNum() { return num; } public void setNum(Double num) { this.num = num; } public Date getBeginDate() { return beginDate; } public void setBeginDate(Date beginDate) { this.beginDate = beginDate; } public Date getEndDate() { return endDate; } public void setEndDate(Date endDate) { this.endDate = endDate; } public String getDestination() { return destination; } public void setDestination(String destination) { this.destination = destination; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } }
启动流程时设置变量
在启动流程时设置流程变量,变量的作用域是整个流程实例。通过Map设置流程变量,map中可以设置多个变量,key就是流程变量的名字
流程变量作用域是一个流程实例,流程变量使用Map存储,同一个流程实例设置变量map中key相同,后者覆盖前者。
//1.创建流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取runtimeService RuntimeService runtimeService = processEngine.getRuntimeService(); //获取到流程的key String processInstanceKey = "buiness-global1"; //设置任务负责人参数 BusinessTrip businessTrip = new BusinessTrip(); businessTrip.setNum(3d); Map variable = new HashMap(); variable.put("businessTrip",businessTrip); variable.put("assignee0","张三员工1"); variable.put("assignee1","李四部门经理1"); variable.put("assignee2","王五总经理1"); variable.put("assignee3","赵六财务1"); //3.根据processInstance的id以及传入的参数进行开启流程 ProcessInstance processInstance = runtimeService .startProcessInstanceByKey(processInstanceKey, variable); //4.输出 System.out.println("流程实例名称="+processInstance.getName()); System.out.println("流程定义id=="+processInstance.getProcessDefinitionId());
任务办理时设置变量:
在完成任务时设置流程变量,该流程变量只有在该任务完成后其他结点才可以使用该变量,它的作用域是整个流程实例,如果设置的流程变量的key在流程实例中已存在相同的名字,则后设置的变量替换前边设置的变量。
//1.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取到taskService TaskService taskService = processEngine.getTaskService(); /*//3.获取需要进行查询的参数67501 String processInstanceId = "55001"; String assignee = "赵六财务";*/ String processInstanceId = "85001"; String assignee = "赵六财务1"; BusinessTrip businessTrip = new BusinessTrip(); businessTrip.setNum(2d); Map<String, Object> map = new HashMap<>(); map.put("businessTrip",businessTrip); //4.创建任务查询 Task task = taskService.createTaskQuery() .processInstanceId(processInstanceId) .taskAssignee(assignee) .singleResult(); if (task != null){ //5.如果task不为空,那么完成任务。 taskService.complete(task.getId(),map); System.out.println("任务执行完成"); }
通过当前流程实例设置:
通过流程实例id设置全局变量,该流程实例必须未执行完成
// 当前流程实例执行 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)
注:
- 如果UEL表达式中流程变量名不存在则报错
- 如果UEL表达式中流程变量值为空null,流程不安UEL表达式去执行,而流程结束。
- 如果UEL表达式都不符合条件,流程结束
- 如果连线不设置条件,会走flow需要小的那条线
四. 组任务
1. 需求
在流程定义中在任务结点的 assignee 固定设置任务负责人,在流程定义时将参与者固定设置在.bpmn 文件中,如果临时任务负责人变更则需要修改流程定义,系统可扩展性差。
针对这种情况可以给任务设置多个候选人,可以从候选人中选择参与者来完成任务。
2. 设置任务候选人
在流程图中任务节点的配置中设置candidate-users(候选人),多个候选人之间用逗号分开。
3. 组任务
组任务办理流程
①. 查询组任务
指定候选人,查询该候选人当前的待办任务
//设置需要获取到的任务查询的条件 String processDefinitionKey = "testcandidate"; String candidateUser = "王副部门经理"; //1.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取taskService TaskService taskService = processEngine.getTaskService(); //3.使用service获取到任务查询list List<Task> list = taskService.createTaskQuery() .processDefinitionKey(processDefinitionKey) .taskCandidateUser(candidateUser) .list(); //4.输出信息 for (Task task : list) { 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()); }
②. 拾取(claim)任务
该任务的所有候选人都能拾取。将候选人的组任务变成个人任务,原来候选人就变成该任务的负责人。
//1.设置需要获取的任务查询条件 String taskId = "105002"; String candidateUser = "王副部门经理"; //2.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //3.获取taskService TaskService taskService = processEngine.getTaskService(); //4.创建任务查询 Task task = taskService.createTaskQuery() .taskId(taskId) .taskCandidateUser(candidateUser) .singleResult(); //5.如果该任务查询出来存在 if(task != null){ //根据任务的id以及拾取候选人为负责人 taskService.claim(task.getId(),candidateUser); System.out.println("任务id--"+taskId+"--的候选人--"+candidateUser+"拾取任务完成"); }
如果拾取后不想办理该任务,需要将已经拾取的个人任务归还到组里,将个人任务变成了组任务。
//1.设置需要获取的任务查询条件 String taskId = "105002"; String assignee = "王副部门经理"; //2.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //3.获取taskService TaskService taskService = processEngine.getTaskService(); //4.创建任务查询 Task task = taskService.createTaskQuery() .taskId(taskId) .taskAssignee(assignee) .singleResult(); //5.如果该任务查询出来存在 if(task != null){ //根据任务的id设置负责人为null即为归还负责人 taskService.setAssignee(task.getId(),null); System.out.println("任务id--"+taskId+"--的负责人--"+assignee+"归还任务完成"); }
任务的交接,实质上就是讲assignee进行修改
String taskId = "105002"; String assignee = "王副部门经理"; String candidateUser = "李部门经理"; //1.获取流程引擎 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2.获取taskService TaskService taskService = processEngine.getTaskService(); //3.根据taskService获取到任务查询 Task task = taskService.createTaskQuery() .taskId(taskId) .taskAssignee(assignee) .singleResult(); //4.如果能够查询出来任务,那么就将任务的负责人进行交接 if(task != null){ taskService.setAssignee(task.getId(),candidateUser); System.out.println("任务id--"+taskId+"--的负责人--"+assignee+"交接任务给"+candidateUser+"完成"); }
③. 查询个人任务
查询方法同个人人物部分,根据assignee查询用户负责的个人任务。
④. 办理个人任务
同以前的完成任务
五. 网关
网管主要是用来控制流程的流向。我们在前面学习了使用UEL表达式的方式直接在连线上来控制流程,但该方法并有时候会造成创建两次流程实例的情况,导致不能按照我们设定的要求进行走向;如果条件都不满足,流程就结束了(异常结束)。所以一般还需要网关进行控制流程走向。
1. 排他网关ExclusiveGateway
①. 概念
排他网关,用在流程中实现决策,当流程执行了该网关,所有的分支会判断条件是否为true。如果为true则执行该分支。
注:
- 排他网关只会选择一个为true的分支执行,如果有两个分支的条件都是true,那么排他网关会选择id值较小的一条分支进行执行。
- 如果排他网关控制的所有分支都不满足true,那么系统会跑出异常。
②. 用法
用法和以前一样,部署、开启流程实例、完成执行实例。
图片如下:
2. 并行网关ParallelGateway
并行网关允许多个分支并行执行,也可以将多条分支汇聚到一起,并行网关的功能基于进入和外出顺序流的:
- fork分支:通过并行网关后将一条流程分成多条分支成外出顺序流,
- join汇聚:所有到达并行网关后,再次等待的进入分支,直到所有进入顺序流的分支都到达之后,流程就会汇聚网关。
注:如果同一个并行网关有多个进入和多个外出顺序流,他就同时具有了分支和汇聚的功能,这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。与其他网关主要区别是,并行网关不会解析条件,即使顺序流定义了条件,也会忽略执行。
3. 包含网关InclusiveGetaway
包含网关可以看做排他网关和并行网关的结合体。
可以和排他网关一样,在顺序流上定义条件,包含网关会解析他们,但是主要区别是包含网关可以选择多与一条顺序流,这和并行网关一样。
如图所示:无论什么条件都会进入到人是审批中。接着从技术经理或项目经理满足条件的一个进行汇聚。
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
这篇关于工作流学习日志 -(Activiti7进阶)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享