1、引言
Activiti作为一款轻量级、开源的工作流和业务流程管理(BPM)平台。流程实例(Process Instance) 是 Activiti 核心运行机制的重要组成部分,代表了一个具体的业务流程从启动到结束的整个生命周期,本文将介绍关于activiti中关于启动、挂起、激活,查询及删除流程实例的方式。
2、启动流程实例
Activiti提供了多种启动流程实例的方式,主要通过RuntimeService、ProcessRuntime等接口实现。
2.1、ProcessInstanceBuilder的使用
ProcessInstanceBuilder是Activiti提供的一种灵活的流程实例构建方式,采用建造者模式(Builder Pattern),可以链式调用设置各种参数。
2.1.1、基本使用如下:
@RestController
@RequestMapping("/process")
public class StartUpProcess {@Autowiredprivate RuntimeService runtimeService;@Autowiredprivate TaskService taskService;@GetMapping(value = "/start")public AjaxResult startProcess() {List<String> assigneeList = new ArrayList<>();assigneeList.add("admin");ProcessInstance instance = runtimeService.createProcessInstanceBuilder().processDefinitionKey("Test-Process") .variable("assigneeList", assigneeList) / 设置流程变量.start();List<Task> tasks = taskService.createTaskQuery().processInstanceId(instance.getId()).list();tasks.forEach(task -> {System.out.println("任务ID: " + task.getId() + ", 处理人: " + task.getAssignee());});return AjaxResult.success("下发成功!");}
}
2.1.2、主要方法说明(见源码:ProcessInstanceBuilder
)
方法 | 说明 | 使用场景 |
---|
processDefinitionKey(String processDefinitionKey); | 通过 流程定义Key 启动流程 | 较为通用方式 |
processDefinitionId(String processDefinitionId); | 通过 流程定义ID 启动流程(精确匹配) | 明确知道流程定义的唯一ID时使用( |
messageName(String messageName); | 通过 消息名称 启动流程(需配合消息启动事件) | BPMN 中定义了 <startEvent activiti:messageName="***"> 时使用 |
name(String processInstanceName); | 设置流程实例的 显示名称(非业务标识) | .- |
businessKey(String businessKey); | 设置流程实例的 业务键(用于业务关联) | - |
tenantId(String tenantId) | 指定 租户ID(多租户隔离) | 确保 tenantId 与流程定义的租户一致 |
variables(Map<String, Object> variables); | 设置 持久化变量(存入数据库) | - |
variable(String variableName, Object value); | 设置 持久化变量(存入数据库) | - |
transientVariables(Map<String, Object> transientVariables); | 设置 临时变量(不存库,仅启动阶段有效) | - |
transientVariable(String variableName, Object value); | 设置 临时变量(不存库,仅启动阶段有效) | - |
start(); | 执行流程启动操作 | - |
2.2、 startProcess系列方法(见源码:RuntimeService
)
2.2.1、按流程定义Key启动
public void startProcess() {ProcessInstance instance1 = runtimeService.startProcessInstanceByKey("Test-Process");ProcessInstance instance2 = runtimeService.startProcessInstanceByKey("Test-Process", "20250413");Map<String, Object> variables = new HashMap<>();variables.put("assignee", "admin");ProcessInstance instance3 = runtimeService.startProcessInstanceByKey("Test-Process", variables);ProcessInstance instance4 = runtimeService.startProcessInstanceByKey("Test-Process", "20250413", variables);}
2.2.2、 按流程定义ID启动
public void startProcess() {ProcessInstance instance1 = runtimeService.startProcessInstanceById("Test-Process:1:9da64eadfc0946d9ba70606");ProcessInstance instance2 = runtimeService.startProcessInstanceById("Test-Process:1:9da64eadfc0946d9ba70606", "20250413");Map<String, Object> variables = new HashMap<>();variables.put("assignee", "admin");ProcessInstance instance3 = runtimeService.startProcessInstanceById("Test-Process:1:9da64eadfc0946d9ba70606", variables);ProcessInstance instance4 = runtimeService.startProcessInstanceById("Test-Process:1:9da64eadfc0946d9ba70606", "20250413", variables);}
2.2.3、 按消息启动
public void startProcess() {ProcessInstance instance1 = runtimeService.startProcessInstanceByMessage("MessageTask");ProcessInstance instance2 = runtimeService.startProcessInstanceByMessage("MessageTask", "20250413");Map<String, Object> variables = new HashMap<>();variables.put("MessageTask", "1000");ProcessInstance instance3 = runtimeService.startProcessInstanceByMessage("MessageTask", variables);ProcessInstance instance4 = runtimeService.startProcessInstanceByMessage("MessageTask", "20250413", variables);}
2.2.4、多租户支持
对于多租户系统,可以使用带tenantId的方法:
public void startProcess() {ProcessInstance instance1 = runtimeService.startProcessInstanceByKeyAndTenantId("Test-Process", "tenant1");ProcessInstance instance2 = runtimeService.startProcessInstanceByMessageAndTenantId("MessageTask", "tenant1");
}
2.3、 ProcessRuntime的start()方法(见源码:ProcessRuntime、ProcessPayloadBuilder
)
2.3.1、基本使用示例:
public void startProcess() {List<String> assigneeList = new ArrayList<>();assigneeList.add("admin");Map<String, Object> variables = new HashMap<>();variables.put("assigneeList", assigneeList);ProcessInstance instance = processRuntime.start(ProcessPayloadBuilder.start().withProcessDefinitionKey("Test-Process").withName("测试").withBusinessKey("businessId").withVariables(variables).build());
}
3、挂起流程实例
3.1、挂起特定流程实例
3.1.1、通过runtimeService.suspendProcessInstanceById()实现
public AjaxResult suspendProcess(){runtimeService.suspendProcessInstanceById("368079dd58c34189a5208c3db269cfa5");return AjaxResult.success();}
3.1.2、通过processRuntime.suspend()实现
public AjaxResult suspendProcess(){processRuntime.suspend(ProcessPayloadBuilder.suspend("368079dd58c34189a5208c3db269cfa5"));processRuntime.suspend(ProcessPayloadBuilder.suspend().withProcessInstanceId("368079dd58c34189a5208c3db269cfa5").build());return AjaxResult.success();
}
3.2、挂起整个流程定义的所有实例
3.2.1、通过RepositoryService.suspendProcessDefinitionByKey()的方式
public AjaxResult suspendProcess(){repositoryService.suspendProcessDefinitionByKey("Test-Process",true, null );return AjaxResult.success();}
3.2.2、通过RepositoryService.suspendProcessDefinitionByKey()的方式
public AjaxResult suspendProcess(){repositoryService.suspendProcessDefinitionById("Test-Process",true, null );return AjaxResult.success();}
4、激活流程实例
4.1、激活特定流程实例
4.1.1、通过runtimeService.activateProcessInstanceById()实现
public AjaxResult activateProcess(){runtimeService.activateProcessInstanceById("368079dd58c34189a5208c3db269cfa5");
return AjaxResult.success();}
4.1.2、通过processRuntime.resume()实现
public AjaxResult activateProcess(){processRuntime.resume(ProcessPayloadBuilder.resume("368079dd58c34189a5208c3db269cfa5")); processRuntime.resume(ProcessPayloadBuilder.resume().withProcessInstanceId("368079dd58c34189a5208c3db269cfa5").build());
return AjaxResult.success();
}
4.2、挂起整个流程定义的所有实例
4.2.1、通过RepositoryService.activateProcessDefinitionByKey()的方式
public AjaxResult activateProcess(){repositoryService.activateProcessDefinitionByKey("Test-Process",true, null );return AjaxResult.success();}
4.2.2、通过RepositoryService.activateProcessDefinitionById()的方式
public AjaxResult activateProcess(){repositoryService.activateProcessDefinitionById("Test-Process",true, null );return AjaxResult.success();}
5、查询流程实例
通过 RuntimeService 和 HistoryService 进行查询
5.1、查询运行时实例
5.1.1、基本使用实例:
public AjaxResult queryInstance(){List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();for (ProcessInstance pd : list) {try {StringBuilder sb = new StringBuilder();for (Field field : pd.getClass().getDeclaredFields()) {field.setAccessible(true);sb.append(field.getName()).append("=").append(field.get(pd)).append(", ");}logger.info("反射字段值: {}", sb.toString());} catch (Exception e) {logger.error("反射读取失败", e);}}return AjaxResult.success();}
5.1.2、主要方法说明(见源码:ProcessInstanceQuery
)
分类 | 方法 | 说明 | 示例 |
---|
基础查询 | processInstanceId(String) | 按流程实例ID查询 | .processInstanceId(“123”) |
| processInstanceBusinessKey(String) | 按业务键查询 | .processInstanceBusinessKey(“ORDER_001”) |
| processDefinitionKey(String) | 按流程定义Key查询 | .processDefinitionKey(“leaveProcess”) |
状态筛选 | suspended() | 查询已挂起的流程实例 | .suspended() |
| active() | 查询活跃的流程实例 | .active() |
时间范围 | startedAfter(Date) | 查询指定时间之后启动的实例 | .startedAfter(new Date(startTime)) |
| startedBefore(Date) | 查询指定时间之前启动的实例 | .startedBefore(new Date(endTime)) |
变量条件 | variableValueEquals(String, Object) | 查询变量等于特定值的实例 | .variableValueEquals(“status”, “approved”) |
| variableValueNotEquals(String, Object) | 查询变量不等于特定值的实例 | .variableValueNotEquals(“priority”, 1) |
| variableValueGreaterThan(String, Object) | 查询变量值大于特定值的实例 | .variableValueGreaterThan(“amount”, 1000) |
排序方法 | orderByProcessInstanceId().desc() | 按实例ID降序排列 | .orderByProcessInstanceId().desc() |
| orderByProcessDefinitionKey().asc() | 按流程定义Key升序排列 | .orderByProcessDefinitionKey().asc() |
分页/计数 | listPage(int firstResult, int maxResults) | 分页查询 | .listPage(0, 10) // 第1页,每页10条 |
| count() | 计数查询 | .processDefinitionKey(“order”).count() |
高级查询 | includeProcessVariables() | 结果包含流程变量 | .includeProcessVariables().list() |
| processInstanceTenantId(String) | 按租户ID查询 | .processInstanceTenantId(“tenant1”) |
| or()…endOr() | 逻辑OR条件组合 | .or().processDefinitionKey(“p1”).processDefinitionKey(“p2”).endOr() |
实用场景 | involvedUser(String) | 查询用户参与的流程实例 | .involvedUser(“user1”).active() |
| startedBy(String) | 查询指定用户启动的实例 | .startedBy(“admin”) |
| withJobException() | 查询因作业异常失败的实例 | .withJobException() |
5.2、查询历史实例
5.2.1、基本使用实例:
public AjaxResult queryInstance(){List<HistoricProcessInstance> list1 = historyService.createHistoricProcessInstanceQuery().list();for (HistoricProcessInstance pd : list1) {try {StringBuilder sb = new StringBuilder();for (Field field : pd.getClass().getDeclaredFields()) {field.setAccessible(true);sb.append(field.getName()).append("=").append(field.get(pd)).append(", ");}logger.info("反射字段值: {}", sb.toString());} catch (Exception e) {logger.error("反射读取失败", e);}}return AjaxResult.success();}
5.1.2、主要方法说明(见源码:HistoricProcessInstanceQuery
)
分类 | 方法 | 说明 | 示例 |
---|
基础查询 | processInstanceId(String) | 按历史流程实例ID查询 | .processInstanceId(“123”) |
| processInstanceBusinessKey(String) | 按业务键查询 | .processInstanceBusinessKey(“ORDER_001”) |
| processDefinitionKey(String) | 按流程定义Key查询 | .processDefinitionKey(“leaveProcess”) |
状态筛选 | finished() | 查询已完成的流程实例 | .finished() |
| unfinished() | 查询未完成的流程实例 | .unfinished() |
| deleted() | 查询已删除的流程实例 | .deleted() |
| notDeleted() | 查询未删除的流程实例 | .notDeleted() |
时间范围 | startedAfter(Date) | 查询指定时间之后启动的实例 | .startedAfter(new Date(startTime)) |
| startedBefore(Date) | 查询指定时间之前启动的实例 | .startedBefore(new Date(endTime)) |
| finishedAfter(Date) | 查询指定时间之后完成的实例 | .finishedAfter(new Date(completionTime)) |
| finishedBefore(Date) | 查询指定时间之前完成的实例 | .finishedBefore(new Date(completionTime)) |
变量条件 | variableValueEquals(String, Object) | 查询结束时有指定变量值的实例 | .variableValueEquals(“status”, “approved”) |
| variableValueNotEquals(String, Object) | 查询结束时变量值不等于指定值的实例 | .variableValueNotEquals(“priority”, 1) |
| variableValueGreaterThan(String, Object) | 查询结束时变量值大于指定值的实例 | .variableValueGreaterThan(“amount”, 1000) |
| variableValueLike(String, String) | 模糊匹配字符串变量值 | .variableValueLike(“comment”, “%urgent%”) |
排序方法 | orderByProcessInstanceId().desc() | 按实例ID降序排列 | .orderByProcessInstanceId().desc() |
| orderByProcessInstanceStartTime().asc() | 按启动时间升序排列 | .orderByProcessInstanceStartTime().asc() |
| orderByProcessInstanceDuration().desc() | 按执行时长降序排列 | .orderByProcessInstanceDuration().desc() |
分页/计数 | listPage(int firstResult, int maxResults) | 分页查询 | .listPage(0, 10) // 第1页,每页10条 |
| count() | 计数查询 | .processDefinitionKey(“order”).count() |
高级查询 | includeProcessVariables() | 结果包含流程变量 | .includeProcessVariables().list() |
| processInstanceTenantId(String) | 按租户ID查询 | .processInstanceTenantId(“tenant1”) |
| or()…endOr() | 逻辑OR条件组合 | .or().processDefinitionKey(“p1”).processDefinitionKey(“p2”).endOr() |
| withJobException() | 查询因作业异常失败的实例 | .withJobException() |
实用场景 | involvedUser(String) | 查询用户参与的历史流程实例 | .involvedUser(“user1”) |
| startedBy(String) | 查询指定用户启动的实例 | .startedBy(“admin”) |
| superProcessInstanceId(String) | 查询子流程实例 | .superProcessInstanceId(“parentProcessId”) |
6、删除流程实例
通过 RuntimeService 或 ProcessRuntime 进行删除
6.1、使用runtimeService.deleteProcessInstance(String processInstanceId, String deleteReason)
public AjaxResult deleteInstance(){runtimeService.deleteProcessInstance("368079dd58c34189a5208c3db269cfa5","测试");return AjaxResult.success();}
6.2、使用processRuntime.delete(DeleteProcessPayload deleteProcessPayload)
public AjaxResult deleteInstance(){processRuntime.delete(ProcessPayloadBuilder.delete("368079dd58c34189a5208c3db269cfa5"));processRuntime.delete(ProcessPayloadBuilder.delete().withProcessInstanceId("368079dd58c34189a5208c3db269cfa5").build());return AjaxResult.success();
}