蘇阿細 - Activiti7
type: channel
link: https://km.wangchouchou.com/category/Activiti7/
description: Activiti7
items: 工作流 - 网关
items: 工作流 - 组任务
items: 工作流 - 流程变量
items: 工作流 - 个人任务
items: 工作流 - 流程实例
items: 工作流 - 基本应用
items: 工作流简介

工作流 - 网关
type: item
date: 2023-05-27T15:12:00+00:00
description: 1. 排他网关 ExclusiveGateway（1）概念排他网关，用来在流程中实现决策。 当流程执行到这个网关，所有分支都会判断条件是否为true，如果 为true则执行该分支，排他网关只会选择一个为true的分支执行，如果有两个分支条件都为true，排他网关会选择id值较小的一条分支去执行当从网关出去的线所有条件都不满足时则会抛出异常org.activiti.engine.ActivitiException: No outgoing sequence flow of the exclusive gateway 'exclusivegateway' could be selected for continuing the process at org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior.leave(ExclusiveGatewayActivityBehavior.java:85)（2）测试public class ExclusiveTest { @Test public void deploy() { //1.获取ProcessEngine对象 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); //2.获取RepositoryService RepositoryService service = engine.getRepositoryService(); //3.部署 Deployment deploy = service.createDeployment() .addClasspathResource("bpmn/evection-exclusive.bpmn") .addClasspathResource("bpmn/evection-exclusive.png") .name("出差申请流程-排他网关") .deploy(); System.out.println("id: " + deploy.getId()); System.out.println("name: " + deploy.getName()); //service.deleteDeployment("57501", true); } @Test public void startProcess() { ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); RuntimeService runtimeService = engine.getRuntimeService(); Evection evection = new Evection(); evection.setNum(4d); Map<String, Object> map = new HashMap<>(); map.put("evection", evection); ProcessInstance instance = runtimeService.startProcessInstanceByKey("evection-exclusive", map); System.out.println("流程定义id：" + instance.getProcessDefinitionId()); } @Test public void completeTask() { String userId = "lisi"; ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); Task task = taskService.createTaskQuery().processDefinitionKey("evection-exclusive").taskAssignee(userId).singleResult(); if (task != null) { Evection evection = new Evection(); evection.setNum(2d); Map<String, Object> map = new HashMap<>(); map.put("evection", evection); taskService.complete(task.getId(), map); System.out.println("任务：" + task.getId() + "完…

工作流 - 组任务
type: item
date: 2023-05-26T15:25:00+00:00
description: 1. 组任务处理流程（1）查询组任务指定候选人，查询该候选人当前的待办任务，候选人不能立即办理任务（2）拾取(claim)任务该组任务的所有候选人都能拾取将候选人的组任务，变成个人任务，原来候选人就变成了该任务的负责人如果拾取后不想办理该任务时怎么办？需要将已经拾取的个人任务归还到组里边，将个人任务变成了组任务（即设置assignee为null）（3）查询个人任务查询方式同理个人任务部分，根据assignee查询用户负责的个人任务（4）办理个人任务同理任务处理2. 查询组任务根据候选人查询组任务@Test public void queryGroupTask() { String key = "evection1"; String candidateUser = "zhangsan"; ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); List<Task> list = taskService.createTaskQuery() .processDefinitionKey(key) .taskCandidateUser(candidateUser) //.taskCandidateOrAssigned(candidateUser) .list(); for (Task task : list) { System.out.println("流程实例id：" + task.getProcessInstanceId()); System.out.println("任务id：" + task.getId()); System.out.println("任务名称：" + task.getName()); System.out.println("负责人：" + task.getAssignee()); } }3. 拾取组任务候选人员拾取组任务后该任务变为自己（即指定候选人）的个人任务@Test public void claimTask() { String taskId = "45002"; String userId = "zhangsan"; ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); Task task = taskService.createTaskQuery().taskId(taskId).taskCandidateUser(userId).singleResult(); if (task != null) { taskService.claim(taskId, userId); System.out.println("任务拾取成功"); } }4. 查询个人待办任务查询方式同理个人任务查询@Test public void queryGroupTask() { String key = "evection1"; String candidateUser = "zhangsan"; 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.getName()); System.out.println("负责人：" + task.getAssignee()); } }5. 办理个人任务@Test public void completeTask() { ProcessEngine engine =…

工作流 - 流程变量
type: item
date: 2023-05-26T15:18:00+00:00
description: 1. 概念流程变量在 activiti 中是一个非常重要的角色，流程运转有时需要靠流程变量，业务系统和 activiti 结合时少不了流程变量，流程变量就是 activiti 在管理工作流时根据管理需要而设置的变量。 如：在出差申请流程流转时如果出差天数大于 3 天则由总经理审核，否则由人事直接审核， 出差天数就可以设置为流程变量，在流程流转时使用。 注：虽然流程变量中可以存储业务数据，可以通过activiti的api查询流程变量从而实现查询业务数据， 但是不建议这样使用，因为业务数据查询由业务系统负责，activiti设置流程变量是为了流程执行需要而创建的。2. 流程变量类型如果将 pojo 存储到流程变量中，必须实现序列化接口 serializable，为了防止由于新增字段无法反序列化，需要生成 serialVersionUID3. 流程变量作用域流程变量的作用域可以是一个流程实例(processInstance)，或一个任务(task)，或一个执行实例 (execution)global变量流程变量的默认作用域是流程实例，当一个流程变量的作用域为流程实例时，可以称为 global 变量注：Global变量：userId（变量名）、xxx（变量值） global 变量中变量名不允许重复，设置相同名称的变量，后设置的值会覆盖前设置的变量值local变量任务和执行实例仅仅是针对一个任务和一个执行实例范围，范围没有流程实例大， 称为 local 变量。Local 变量由于在不同的任务或不同的执行实例中，作用域互不影响，变量名可以相同没有影响。Local 变量名也可以和 global 变量名相同，也是没有影响的4. 流程表变量的使用方法（1）在属性上使用UEL表达式可以在 assignee 处设置 UEL 表达式，表达式的值为任务的负责人，比如： ${assignee}， assignee 就 是一个流程变量名称， Activiti获取UEL表达式的值，即流程变量assignee的值 ，将assignee的值作为任务的负责人进行任务分配（2）在连线上使用UEL表达式可以在连线上设置UEL表达式，决定流程走向。 比如：${price<10000} ，price就是一个流程变量名称，uel表达式结果类型为布尔类型， 如果UEL表达式是true，则决定流程执行走向（即流程走这条连线）5. 使用流程变量例：员工创建出差申请单，由部门经理审核，部门经理申请通过后3天以下由财务直接申批，3天以上先由总经理审批，总经理审批通过后再由财务审批（1）流程定义先通过UEL-value来设置负责人然后在分支线上来设置条件注：此处还可以通过对象参数命名，比如 evection.num另一根线对应的设置设置完成之后即可部署流程（2）使用global变量创建pojo对象public class Evection implements Serializable { /** * id */ private long id; /** * 名称 */ private String evectionName; /** * 出差天数 */ private double num; /** * 开始日期 */ private Date startDate; /** * 结束日期 */ private Date endDate; /** * 目的地 */ private String destination; /** * 事由 */ private String reason; public Evection() { } public Evection(long id, String evectionName, double num, Date startDate, Date endDate, String destination, String reason) { this.id = id; this.evectionName = evectionName; this.num = num; this.startDate = startDate; this.endDate = endDate; this.destination = destination; this.reason = reason; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getEvectionName() { return evectionName; } public void setEvectionName(String evectionName) { t…

工作流 - 个人任务
type: item
date: 2023-05-25T14:30:00+00:00
description: 1. 分配任务负责人（1）固定分配在进行业务流程设计的时候指定固定的任务负责人Properties ---> Main Config ---> Assignee（2）表达式分配在Activiti中支持使用UEL表达式，UEL表达式是Java EE6 规范的一部分， UEL(Unified Expression Language) 即统一表达式语言Activiti支持两种UEL表达式： UEL-value 和 UEL-methodUEL-value创建一个新的流程使用表达式之后的几个负责人以 ${assignee0}, ${assignee1}...的形式以此类推流程绘制完成之后，进行部署，在启动流程实例时给 UEL 表达式赋值@Test public void deploy() { //1.获取ProcessEngine对象 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); //2.获取RepositoryService RepositoryService service = engine.getRepositoryService(); //3.部署 Deployment deploy = service.createDeployment() .addClasspathResource("bpmn/evection-uel.bpmn") .addClasspathResource("bpmn/evection-uel.png") .name("出差申请流程-UEL") .deploy(); System.out.println("id: " + deploy.getId()); System.out.println("name: " + deploy.getName()); } @Test public void createProcess() { ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); RuntimeService service = engine.getRuntimeService(); //设置assignee Map<String, Object> map = new HashMap<>(); map.put("assignee0", "zhangsan"); map.put("assignee1", "lisi"); map.put("assignee2", "wangwu"); map.put("assignee3", "xiaoming"); service.startProcessInstanceByKey("evection-uel", map); }启动成功后，可在 act_ru_variable 表中查找对应的赋值信息UEL-methodUserBean即注册到Spring容器中的Bean，表示调用该对象的 getUserId 方法UEL-method 与 UEL-value 结合如： ${userService.findManager(emp)}userService 是 Spring 容器的一个bean，findManager 是该 bean 的一个方法，emp 是 activiti 流程变量， emp作为参数传到 userService.findManager 方法中其他表达式支持解析基础类型、 bean、 list、 array 和 map，也可作为条件判断，如： ${order.price > 100 && order.price < 250}（3）分配监听器使用监听器来完成负责人的指定，在流程设计的时候就不需要指定assignee Event选项Event分类：create:任务创建后触发assignment：任务分配后触发Delete：任务完成后触发All：所有事件都触发自定义监听器package com.sw.listener; import org.activiti.engine.delegate.DelegateTask; public class TaskListener implements org.activiti.engine.delegate.TaskListener { @Override public void notify(DelegateTask delegateTask) { if ("创建请假单".equals(delegateTask.getName()) && "create".equals(delegateTask.getEventName())) { //指定任务负责人 delegateT…

工作流 - 流程实例
type: item
date: 2023-05-25T14:29:00+00:00
description: 1. 概念流程实例(ProcessInstance)代表流程定义的执行实例一个流程实例包括了所有的运行节点，可以通过这个对象来了解当前流程实例的进度等信息，例如：用户或者程序按照流程定义的内容发起了一个流程，这就是一个流程实例2. 业务管理流程定义部署在Activiti后，我们就可以在系统中通过Activiti去管理流程的执行，但是如果要将流程实例和业务数据关联，这时需要使用到Activiti中预留的BusinessKey（业务标识）来关联@Test public void associateBusinessKey() { //1.获取ProcessEngine对象 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); //2.RuntimeService RuntimeService service = engine.getRuntimeService(); //3.启动流程，添加businessKey ProcessInstance instance = service.startProcessInstanceByKey("evection", "10001"); System.out.println("businessKey: " + instance.getBusinessKey()); }3. 流程实例的挂起和激活在实际场景中可能由于流程变更需要将当前运行的流程暂停而不删除，流程暂停后将不能继续执行（1）全部流程挂起操作流程的定义为挂起状态，该流程定义下边所有的流程实例全部暂停。 流程定义为挂起状态时，该流程定义将不允许启动新的流程实例，同时该流程定义下的所有的流程实例都将全部挂起暂停执行@Test public void processSuspendOrActive() { //1.获取ProcessEngine对象 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); //2.RepositoryService RepositoryService service = engine.getRepositoryService(); //3.查询流程定义的对象 ProcessDefinition definition = service.createProcessDefinitionQuery().processDefinitionKey("evection").singleResult(); //4.获取当前流程定义的状态 String id = definition.getId(); boolean suspended = definition.isSuspended(); //5.挂起 ---> 激活，否则反之 if (suspended) { service.activateProcessDefinitionById(id, true, null); System.out.println("流程：" + id + "，已激活"); } else { service.suspendProcessDefinitionById(id, true, null); System.out.println("流程：" + id + "，已挂起"); } }注：挂起流程定义后，实例对象中（数据库数据的状态）的状态会修改为 2，此时如果再去操作对应的流程实例会抛出异常，将挂起的流程转变为激活状态，则对应的状态值会从 2 更新为 1（即可以正常处理业务流程）4. 单个实例挂起针对单个流程执行挂起操作，则将指定的流程实例挂起，当前流程定义的其他流程实例不受干扰，此时如果去操作已挂起的该流程实例，同理会抛出异常@Test public void singleProcessSuspendOrActive() { //1.获取ProcessEngine对象 ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); //2.RuntimeService RuntimeService service = engine.getRuntimeService(); //3.查询流程实例对象 ProcessInstance instance = service.createProcessInstanceQuery().processInstanceId("2501").singleResult(); //4.获取相关状态 String id = instance.getId(); boolean suspended = insta…

工作流 - 基本应用
type: item
date: 2023-05-23T14:34:00+00:00
description: 1. 基本使用（1）创建Maven应用pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sw</groupId> <artifactId>ActivitiDemo</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <slf4j.version>1.6.6</slf4j.version> <log4j.version>1.2.12</log4j.version> <activiti.version>7.0.0.Beta1</activiti.version> <mysql.version>8.0.26</mysql.version> <mybatis.version>3.5.13</mybatis.version> <dbcp.version>1.4</dbcp.version> <junit.version>4.12</junit.version> <commons-io.version>2.6</commons-io.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> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-model</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-converter</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-json-converter</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-bpmn-layout</artifactId> <version>${activiti.version}</version> <exclusions> <exclusion> <groupId>com.github.jgraph</groupId> <artifactId>jgraphx</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.activiti.cloud</groupId> <artifactId>activiti-cloud-services-api</a…

工作流简介
type: item
date: 2023-05-23T14:33:00+00:00
description: 参考B站 波哥是个憨憨 Activiti教程Activiti是一个工作流引擎，业务系统访问（操作）activiti的接口，就可以方便的操作流程相关数据，这样就可以把工作流环境与业务系统的环境集成在一起。1. 流程定义使用activiti流程建模工具 activity-designer 定义业务流程 .bpmn 文件， .bpmn 文件就是业务流程定义文件，通过 xml 定义业务流程。2. 流程定义部署activiti部署业务流程定义 .bpmn 文件，使用 activiti 提供的api把流程定义内容存储起来，在Activiti执行过程中可以查询定义的内容。3. 流程实例流程实例(ProcessInstance)：启动一个流程实例表示开始一次业务流程的运行。 在员工请假流程定义部署完成后，如果张三要请假就可以启动一个流程实例，如果李四要请假也启动一 个流程实例，两个流程的执行互相不影响。4. 待办任务待办任务(Task)：因为现在系统的业务流程已经交给 activiti 管理，通过 activiti 就可以查询当前流程执行到哪了，当前用户需要办理什么任务了，这些 activiti 帮我们管理了，而不需要开发人员自己编写在sql语句查询。5. 用户办理任务用户查询待办任务后，就可以办理某个任务，如果这个任务办理完成还需要其它用户办理，比如采购单：创建后由部门经理审核，这个过程也是由 activiti 帮我们完成。6. 流程结束当任务办理完成没有下一个任务结点，表明这个流程实例完成。