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 {
@Autowired
private RuntimeService runtimeService;
@Autowired
private 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 ( ) ;
}