流程实例运行时控制: 启动、暂停、终止、跳转、撤回
2025/8/30大约 15 分钟
在企业级BPM平台中,流程实例运行时控制是流程引擎的核心功能之一,它允许管理员和用户在流程执行过程中对流程实例进行各种操作,包括启动、暂停、终止、跳转、撤回等。一个完善的运行时控制机制不仅能够提升用户体验,还能为业务流程的灵活管理提供强有力的技术支撑。本文将深入探讨流程实例运行时控制的设计与实现。
流程实例运行时控制的核心价值
业务流程灵活性
运行时控制为业务流程提供了极大的灵活性:
- 动态调整:在流程执行过程中动态调整执行路径
- 异常处理:处理流程执行中的异常情况
- 业务干预:允许业务人员干预流程执行
- 流程优化:基于实际执行情况进行流程优化
用户体验提升
完善的运行时控制机制能够显著提升用户体验:
- 操作便捷:提供简单直观的操作界面
- 响应及时:快速响应用户的操作请求
- 反馈明确:提供明确的操作结果反馈
- 权限控制:确保操作的安全性和合规性
管理效率提高
运行时控制为流程管理提供了高效的工具:
- 集中管理:通过统一界面管理所有流程实例
- 批量操作:支持批量处理多个流程实例
- 监控预警:实时监控流程执行状态并预警
- 审计追踪:完整记录所有操作历史
运行时控制操作详解
流程实例启动
流程实例启动是运行时控制的第一个环节:
启动方式
API启动
public class ProcessInstanceStarter {
public ProcessInstance startProcessInstanceByKey(String processDefinitionKey,
Map<String, Object> variables) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
}
public ProcessInstance startProcessInstanceById(String processDefinitionId,
Map<String, Object> variables) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.startProcessInstanceById(processDefinitionId, variables);
}
public ProcessInstance startProcessInstanceByMessage(String messageName,
Map<String, Object> variables) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.startProcessInstanceByMessage(messageName, variables);
}
}表单启动
public class FormBasedStarter {
public ProcessInstance startWithForm(String processDefinitionId,
FormData formData) {
// 验证表单数据
validateFormData(formData);
// 转换表单数据为流程变量
Map<String, Object> variables = convertFormDataToVariables(formData);
// 启动流程实例
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance instance = runtimeService.startProcessInstanceById(
processDefinitionId, variables);
// 关联表单数据
linkFormDataToProcessInstance(instance.getId(), formData);
return instance;
}
private void validateFormData(FormData formData) {
// 表单数据验证逻辑
for (FormField field : formData.getFields()) {
if (field.isRequired() && (field.getValue() == null || field.getValue().toString().isEmpty())) {
throw new FormValidationException("必填字段不能为空: " + field.getId());
}
}
}
private Map<String, Object> convertFormDataToVariables(FormData formData) {
Map<String, Object> variables = new HashMap<>();
for (FormField field : formData.getFields()) {
variables.put(field.getId(), field.getValue());
}
return variables;
}
}启动参数
流程变量
public class ProcessVariableManager {
public void setProcessVariables(String processInstanceId,
Map<String, Object> variables) {
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.setVariables(processInstanceId, variables);
}
public Object getProcessVariable(String processInstanceId, String variableName) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.getVariable(processInstanceId, variableName);
}
public Map<String, Object> getProcessVariables(String processInstanceId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.getVariables(processInstanceId);
}
// 支持不同数据类型的变量
public void setTypedProcessVariables(String processInstanceId,
Map<String, TypedValue> typedVariables) {
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.setVariables(processInstanceId, typedVariables);
}
}业务键关联
public class BusinessKeyManager {
public ProcessInstance startProcessWithBusinessKey(String processDefinitionKey,
String businessKey,
Map<String, Object> variables) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.startProcessInstanceByKey(processDefinitionKey,
businessKey, variables);
}
public ProcessInstance findProcessInstanceByBusinessKey(String businessKey) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.createProcessInstanceQuery()
.processInstanceBusinessKey(businessKey)
.singleResult();
}
public List<ProcessInstance> findProcessInstancesByBusinessKey(String businessKey) {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.createProcessInstanceQuery()
.processInstanceBusinessKey(businessKey)
.list();
}
}流程实例暂停
流程实例暂停允许临时停止流程执行:
暂停实现
public class ProcessInstanceSuspender {
public void suspendProcessInstance(String processInstanceId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
// 检查流程实例状态
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance == null) {
throw new ProcessEngineException("流程实例不存在: " + processInstanceId);
}
if (instance.isSuspended()) {
throw new ProcessEngineException("流程实例已处于暂停状态: " + processInstanceId);
}
// 执行暂停操作
runtimeService.suspendProcessInstanceById(processInstanceId);
// 记录操作日志
auditLog("SUSPEND", processInstanceId, "流程实例已暂停");
}
public void suspendProcessInstancesByProcessDefinition(String processDefinitionId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.suspendProcessInstanceByProcessDefinitionId(processDefinitionId);
}
public void suspendProcessInstancesByProcessDefinitionKey(String processDefinitionKey) {
RuntimeService runtimeService = processEngine.getRuntimeService();
runtimeService.suspendProcessInstanceByProcessDefinitionKey(processDefinitionKey);
}
}暂停状态管理
public class SuspensionStateManager {
public boolean isProcessInstanceSuspended(String processInstanceId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
return instance != null && instance.isSuspended();
}
public List<ProcessInstance> findSuspendedProcessInstances() {
RuntimeService runtimeService = processEngine.getRuntimeService();
return runtimeService.createProcessInstanceQuery()
.suspended()
.list();
}
public void resumeProcessInstance(String processInstanceId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
// 检查流程实例状态
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance == null) {
throw new ProcessEngineException("流程实例不存在: " + processInstanceId);
}
if (!instance.isSuspended()) {
throw new ProcessEngineException("流程实例未处于暂停状态: " + processInstanceId);
}
// 执行恢复操作
runtimeService.activateProcessInstanceById(processInstanceId);
// 记录操作日志
auditLog("RESUME", processInstanceId, "流程实例已恢复");
}
}流程实例终止
流程实例终止用于强制结束流程执行:
终止实现
public class ProcessInstanceTerminator {
public void deleteProcessInstance(String processInstanceId, String deleteReason) {
RuntimeService runtimeService = processEngine.getRuntimeService();
// 检查流程实例是否存在
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance == null) {
throw new ProcessEngineException("流程实例不存在: " + processInstanceId);
}
// 执行删除操作
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
// 记录操作日志
auditLog("DELETE", processInstanceId, "流程实例已终止,原因: " + deleteReason);
}
public void deleteProcessInstances(List<String> processInstanceIds, String deleteReason) {
for (String processInstanceId : processInstanceIds) {
try {
deleteProcessInstance(processInstanceId, deleteReason);
} catch (Exception e) {
// 记录单个实例删除失败,继续处理其他实例
log.error("删除流程实例失败: " + processInstanceId, e);
}
}
}
public void deleteProcessInstancesByBusinessKey(String businessKey, String deleteReason) {
List<ProcessInstance> instances = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processInstanceBusinessKey(businessKey)
.list();
List<String> instanceIds = instances.stream()
.map(ProcessInstance::getId)
.collect(Collectors.toList());
deleteProcessInstances(instanceIds, deleteReason);
}
}终止原因管理
public class TerminationReasonManager {
public static final String REASON_USER_REQUEST = "USER_REQUEST";
public static final String REASON_BUSINESS_CANCEL = "BUSINESS_CANCEL";
public static final String REASON_SYSTEM_ERROR = "SYSTEM_ERROR";
public static final String REASON_TIMEOUT = "TIMEOUT";
public static final String REASON_COMPLIANCE = "COMPLIANCE";
public void deleteProcessInstanceWithReason(String processInstanceId, String reasonCode) {
String deleteReason = buildDeleteReason(reasonCode);
deleteProcessInstance(processInstanceId, deleteReason);
}
private String buildDeleteReason(String reasonCode) {
switch (reasonCode) {
case REASON_USER_REQUEST:
return "用户主动终止";
case REASON_BUSINESS_CANCEL:
return "业务取消";
case REASON_SYSTEM_ERROR:
return "系统错误";
case REASON_TIMEOUT:
return "超时终止";
case REASON_COMPLIANCE:
return "合规要求";
default:
return "其他原因";
}
}
public List<ProcessInstanceHistory> findTerminatedProcessInstances(Date startTime, Date endTime) {
HistoryService historyService = processEngine.getHistoryService();
return historyService.createHistoricProcessInstanceQuery()
.finished()
.startedAfter(startTime)
.startedBefore(endTime)
.list();
}
}流程执行跳转
流程执行跳转允许在流程执行过程中跳转到指定节点:
跳转实现
public class ProcessInstanceJumper {
public void jumpToActivity(String processInstanceId, String activityId) {
RuntimeService runtimeService = processEngine.getRuntimeService();
// 获取当前执行实例
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(processInstanceId)
.list();
if (executions.isEmpty()) {
throw new ProcessEngineException("未找到流程实例的执行实例: " + processInstanceId);
}
// 执行跳转操作
for (Execution execution : executions) {
if (execution.getActivityId() != null) {
// 创建跳转命令
Command<Void> jumpCommand = new JumpActivityCommand(
execution.getId(), activityId);
processEngine.getManagementService().executeCommand(jumpCommand);
}
}
// 记录操作日志
auditLog("JUMP", processInstanceId, "流程执行跳转到节点: " + activityId);
}
// 自定义跳转命令
public static class JumpActivityCommand implements Command<Void> {
private String executionId;
private String targetActivityId;
public JumpActivityCommand(String executionId, String targetActivityId) {
this.executionId = executionId;
this.targetActivityId = targetActivityId;
}
@Override
public Void execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager =
commandContext.getExecutionEntityManager();
ExecutionEntity execution = executionEntityManager.findById(executionId);
if (execution == null) {
throw new ProcessEngineException("执行实例不存在: " + executionId);
}
// 获取目标活动
ProcessDefinitionEntity processDefinition = execution.getProcessDefinition();
ActivityImpl targetActivity = processDefinition.findActivity(targetActivityId);
if (targetActivity == null) {
throw new ProcessEngineException("目标活动不存在: " + targetActivityId);
}
// 执行跳转
execution.executeActivity(targetActivity);
return null;
}
}
}条件跳转
public class ConditionalJumper {
public void jumpIfCondition(String processInstanceId,
String condition,
String targetActivityId) {
// 评估条件
boolean conditionResult = evaluateCondition(processInstanceId, condition);
if (conditionResult) {
// 条件满足,执行跳转
jumpToActivity(processInstanceId, targetActivityId);
}
}
private boolean evaluateCondition(String processInstanceId, String condition) {
// 获取流程变量
Map<String, Object> variables = processEngine.getRuntimeService()
.getVariables(processInstanceId);
// 使用表达式引擎评估条件
ExpressionManager expressionManager = processEngine.getProcessEngineConfiguration()
.getExpressionManager();
Expression expression = expressionManager.createExpression(condition);
return (Boolean) expression.getValue(variables);
}
public void jumpBasedOnBusinessRule(String processInstanceId,
String ruleName,
Map<String, Object> context) {
// 调用业务规则引擎评估规则
RuleService ruleService = processEngine.getRuleService();
List<Map<String, Object>> results = ruleService.executeRules(ruleName, context);
if (!results.isEmpty()) {
Map<String, Object> result = results.get(0);
String targetActivityId = (String) result.get("targetActivityId");
if (targetActivityId != null) {
jumpToActivity(processInstanceId, targetActivityId);
}
}
}
}流程任务撤回
流程任务撤回允许将已处理的任务撤回重新处理:
撤回实现
public class TaskWithdrawManager {
public void withdrawTask(String taskId, String reason) {
TaskService taskService = processEngine.getTaskService();
HistoryService historyService = processEngine.getHistoryService();
// 获取任务信息
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
// 查询历史任务
HistoricTaskInstance historicTask = historyService.createHistoricTaskInstanceQuery()
.taskId(taskId)
.singleResult();
if (historicTask == null) {
throw new ProcessEngineException("任务不存在: " + taskId);
}
if (historicTask.getEndTime() == null) {
throw new ProcessEngineException("任务尚未完成,无法撤回: " + taskId);
}
// 执行撤回操作
executeTaskWithdrawal(historicTask, reason);
} else {
throw new ProcessEngineException("任务尚未完成,无法撤回: " + taskId);
}
}
private void executeTaskWithdrawal(HistoricTaskInstance historicTask, String reason) {
// 创建新的任务实例
Task newTask = processEngine.getTaskService().newTask();
newTask.setName(historicTask.getName());
newTask.setDescription(historicTask.getDescription());
newTask.setPriority(historicTask.getPriority());
newTask.setOwner(historicTask.getOwner());
newTask.setAssignee(historicTask.getAssignee());
newTask.setProcessInstanceId(historicTask.getProcessInstanceId());
newTask.setExecutionId(historicTask.getExecutionId());
newTask.setProcessDefinitionId(historicTask.getProcessDefinitionId());
newTask.setTaskDefinitionKey(historicTask.getTaskDefinitionKey());
processEngine.getTaskService().saveTask(newTask);
// 更新流程执行状态
updateProcessInstanceState(historicTask.getProcessInstanceId(),
historicTask.getTaskDefinitionKey());
// 记录操作日志
auditLog("WITHDRAW", historicTask.getProcessInstanceId(),
"任务撤回: " + historicTask.getName() + ", 原因: " + reason);
}
private void updateProcessInstanceState(String processInstanceId, String activityId) {
// 获取执行实例
Execution execution = processEngine.getRuntimeService()
.createExecutionQuery()
.processInstanceId(processInstanceId)
.activityId(activityId)
.singleResult();
if (execution != null) {
// 将执行实例状态回退到指定活动
// 这里需要根据具体的流程引擎实现来处理
}
}
}撤回权限控制
public class WithdrawalPermissionManager {
public boolean canWithdrawTask(String taskId, String userId) {
TaskService taskService = processEngine.getTaskService();
HistoryService historyService = processEngine.getHistoryService();
IdentityService identityService = processEngine.getIdentityService();
// 获取任务信息
HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery()
.taskId(taskId)
.singleResult();
if (task == null) {
return false;
}
// 检查用户权限
// 1. 任务处理者本人
if (userId.equals(task.getAssignee())) {
return true;
}
// 2. 任务所有者
if (userId.equals(task.getOwner())) {
return true;
}
// 3. 管理员权限
if (identityService.createGroupQuery()
.groupMember(userId)
.groupType("admin")
.count() > 0) {
return true;
}
// 4. 流程实例启动者
HistoricProcessInstance processInstance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(task.getProcessInstanceId())
.singleResult();
if (processInstance != null && userId.equals(processInstance.getStartUserId())) {
return true;
}
return false;
}
public void withdrawTaskWithPermissionCheck(String taskId, String userId, String reason) {
if (!canWithdrawTask(taskId, userId)) {
throw new ProcessEngineException("用户无权撤回任务: " + taskId);
}
withdrawTask(taskId, reason);
}
}运行时控制的实现机制
状态机模型
流程实例运行时控制基于状态机模型实现:
状态定义
public enum ProcessInstanceState {
ACTIVE("active"), // 活跃状态
SUSPENDED("suspended"), // 暂停状态
COMPLETED("completed"), // 完成状态
TERMINATED("terminated"), // 终止状态
ERROR("error"); // 错误状态
private String state;
ProcessInstanceState(String state) {
this.state = state;
}
public String getState() {
return state;
}
}状态转换
public class ProcessInstanceStateMachine {
public void transitionState(String processInstanceId,
ProcessInstanceState fromState,
ProcessInstanceState toState) {
// 验证状态转换的合法性
if (!isValidTransition(fromState, toState)) {
throw new ProcessEngineException("非法的状态转换: " + fromState + " -> " + toState);
}
// 执行状态转换
updateProcessInstanceState(processInstanceId, toState);
// 触发状态转换事件
fireEvent(new StateTransitionEvent(processInstanceId, fromState, toState));
}
private boolean isValidTransition(ProcessInstanceState fromState,
ProcessInstanceState toState) {
// 定义合法的状态转换
switch (fromState) {
case ACTIVE:
return toState == SUSPENDED || toState == COMPLETED ||
toState == TERMINATED || toState == ERROR;
case SUSPENDED:
return toState == ACTIVE || toState == TERMINATED;
case COMPLETED:
return false; // 完成状态不能转换到其他状态
case TERMINATED:
return false; // 终止状态不能转换到其他状态
case ERROR:
return toState == ACTIVE || toState == TERMINATED;
default:
return false;
}
}
private void updateProcessInstanceState(String processInstanceId,
ProcessInstanceState state) {
// 更新数据库中的状态
ProcessInstanceEntityManager entityManager = Context.getCommandContext()
.getProcessInstanceEntityManager();
ProcessInstanceEntity instance = entityManager.findById(processInstanceId);
if (instance != null) {
instance.setSuspensionState(state.ordinal());
}
}
}事件驱动机制
运行时控制通过事件驱动机制实现异步处理:
事件定义
public class RuntimeControlEvent {
private String eventType;
private String processInstanceId;
private String userId;
private Map<String, Object> parameters;
private Date timestamp;
// 构造函数、getter和setter方法
public static class Builder {
private RuntimeControlEvent event = new RuntimeControlEvent();
public Builder eventType(String eventType) {
event.setEventType(eventType);
return this;
}
public Builder processInstanceId(String processInstanceId) {
event.setProcessInstanceId(processInstanceId);
return this;
}
public Builder userId(String userId) {
event.setUserId(userId);
return this;
}
public Builder parameter(String key, Object value) {
if (event.getParameters() == null) {
event.setParameters(new HashMap<>());
}
event.getParameters().put(key, value);
return this;
}
public RuntimeControlEvent build() {
event.setTimestamp(new Date());
return event;
}
}
}事件处理器
public class RuntimeControlEventHandler {
public void handleEvent(RuntimeControlEvent event) {
switch (event.getEventType()) {
case "PROCESS_START":
handleProcessStart(event);
break;
case "PROCESS_SUSPEND":
handleProcessSuspend(event);
break;
case "PROCESS_RESUME":
handleProcessResume(event);
break;
case "PROCESS_TERMINATE":
handleProcessTerminate(event);
break;
case "PROCESS_JUMP":
handleProcessJump(event);
break;
case "TASK_WITHDRAW":
handleTaskWithdraw(event);
break;
default:
log.warn("未知的事件类型: " + event.getEventType());
}
}
private void handleProcessStart(RuntimeControlEvent event) {
String processDefinitionKey = (String) event.getParameters().get("processDefinitionKey");
Map<String, Object> variables = (Map<String, Object>) event.getParameters().get("variables");
// 异步启动流程实例
CompletableFuture.supplyAsync(() -> {
return processEngine.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey, variables);
}).thenAccept(processInstance -> {
// 记录启动成功的日志
log.info("流程实例启动成功: " + processInstance.getId());
}).exceptionally(throwable -> {
// 记录启动失败的日志
log.error("流程实例启动失败", throwable);
return null;
});
}
// 其他事件处理方法...
}权限控制与安全机制
基于角色的访问控制
实现细粒度的权限控制:
权限模型
public class RuntimeControlPermission {
private String resourceId;
private String resourceType;
private String permission;
private String userId;
private String groupId;
// 构造函数、getter和setter方法
}
public class PermissionManager {
public boolean checkPermission(String userId, String resourceId, String permission) {
// 检查用户直接权限
if (hasDirectPermission(userId, resourceId, permission)) {
return true;
}
// 检查用户组权限
List<Group> userGroups = processEngine.getIdentityService()
.createGroupQuery()
.groupMember(userId)
.list();
for (Group group : userGroups) {
if (hasGroupPermission(group.getId(), resourceId, permission)) {
return true;
}
}
return false;
}
private boolean hasDirectPermission(String userId, String resourceId, String permission) {
// 查询用户直接权限
return processEngine.getAuthorizationService()
.createAuthorizationQuery()
.userId(userId)
.resourceId(resourceId)
.permission(permission)
.count() > 0;
}
private boolean hasGroupPermission(String groupId, String resourceId, String permission) {
// 查询用户组权限
return processEngine.getAuthorizationService()
.createAuthorizationQuery()
.groupId(groupId)
.resourceId(resourceId)
.permission(permission)
.count() > 0;
}
}权限验证
public class PermissionAwareRuntimeController {
private PermissionManager permissionManager;
public void startProcessInstance(String userId, String processDefinitionKey,
Map<String, Object> variables) {
// 验证启动权限
if (!permissionManager.checkPermission(userId, processDefinitionKey, "START")) {
throw new SecurityException("用户无权启动流程: " + processDefinitionKey);
}
// 执行启动操作
ProcessInstanceStarter starter = new ProcessInstanceStarter();
starter.startProcessInstanceByKey(processDefinitionKey, variables);
}
public void suspendProcessInstance(String userId, String processInstanceId) {
// 验证暂停权限
if (!permissionManager.checkPermission(userId, processInstanceId, "SUSPEND")) {
throw new SecurityException("用户无权暂停流程实例: " + processInstanceId);
}
// 执行暂停操作
ProcessInstanceSuspender suspender = new ProcessInstanceSuspender();
suspender.suspendProcessInstance(processInstanceId);
}
// 其他权限验证方法...
}操作审计与日志
完整的操作审计机制确保操作的可追溯性:
审计日志
public class AuditLogEntry {
private String id;
private String operationType;
private String resourceId;
private String userId;
private String userName;
private String details;
private Date timestamp;
private String ipAddress;
// 构造函数、getter和setter方法
}
public class AuditLogger {
public void logOperation(String operationType, String resourceId,
String userId, String details) {
AuditLogEntry entry = new AuditLogEntry();
entry.setId(IdGenerator.getNextId());
entry.setOperationType(operationType);
entry.setResourceId(resourceId);
entry.setUserId(userId);
entry.setUserName(getUserName(userId));
entry.setDetails(details);
entry.setTimestamp(new Date());
entry.setIpAddress(getClientIpAddress());
// 异步保存审计日志
CompletableFuture.runAsync(() -> {
saveAuditLog(entry);
});
}
private String getUserName(String userId) {
User user = processEngine.getIdentityService().createUserQuery()
.userId(userId)
.singleResult();
return user != null ? user.getFirstName() + " " + user.getLastName() : userId;
}
private void saveAuditLog(AuditLogEntry entry) {
// 保存到数据库
AuditLogEntityManager entityManager = Context.getCommandContext()
.getAuditLogEntityManager();
entityManager.insert(entry);
}
}性能优化与最佳实践
批量操作优化
public class BatchRuntimeController {
public void batchSuspendProcessInstances(List<String> processInstanceIds) {
// 使用批处理优化
processEngine.getManagementService().executeCommand(
new BatchSuspendCommand(processInstanceIds));
}
public void batchTerminateProcessInstances(List<String> processInstanceIds,
String deleteReason) {
processEngine.getManagementService().executeCommand(
new BatchTerminateCommand(processInstanceIds, deleteReason));
}
// 批处理命令实现
public static class BatchSuspendCommand implements Command<Void> {
private List<String> processInstanceIds;
public BatchSuspendCommand(List<String> processInstanceIds) {
this.processInstanceIds = processInstanceIds;
}
@Override
public Void execute(CommandContext commandContext) {
ProcessInstanceEntityManager entityManager =
commandContext.getProcessInstanceEntityManager();
for (String processInstanceId : processInstanceIds) {
ProcessInstanceEntity instance = entityManager.findById(processInstanceId);
if (instance != null && !instance.isSuspended()) {
instance.setSuspensionState(ProcessInstanceState.SUSPENDED.ordinal());
}
}
return null;
}
}
}缓存优化
public class CachedRuntimeController {
private final Cache<String, ProcessInstance> processInstanceCache;
public CachedRuntimeController() {
processInstanceCache = Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
}
public ProcessInstance getProcessInstance(String processInstanceId) {
return processInstanceCache.get(processInstanceId, id -> {
return processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processInstanceId(id)
.singleResult();
});
}
public void invalidateCache(String processInstanceId) {
processInstanceCache.invalidate(processInstanceId);
}
}案例分析
案例一:某电商企业的订单流程控制
某电商企业在处理订单流程时,需要灵活的运行时控制能力:
业务场景
- 订单取消:用户可以取消未发货的订单
- 流程暂停:系统维护期间暂停订单处理
- 异常跳转:处理支付异常等特殊情况
- 任务撤回:客服可以撤回错误处理的订单
技术实现
public class OrderProcessController {
public void cancelOrder(String orderId, String userId) {
// 查找关联的流程实例
ProcessInstance processInstance = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processInstanceBusinessKey(orderId)
.singleResult();
if (processInstance == null) {
throw new OrderException("订单流程实例不存在: " + orderId);
}
// 验证取消权限
if (!canUserCancelOrder(userId, orderId)) {
throw new SecurityException("用户无权取消订单: " + orderId);
}
// 终止流程实例
processEngine.getRuntimeService().deleteProcessInstance(
processInstance.getId(), "用户取消订单");
// 更新订单状态
updateOrderStatus(orderId, OrderStatus.CANCELLED);
// 记录操作日志
auditLog("ORDER_CANCEL", orderId, "用户取消订单: " + userId);
}
public void pauseOrderProcessing(String userId) {
// 验证管理员权限
if (!isAdminUser(userId)) {
throw new SecurityException("用户无权暂停订单处理");
}
// 暂停所有订单流程实例
List<ProcessInstance> orderProcesses = processEngine.getRuntimeService()
.createProcessInstanceQuery()
.processDefinitionKey("orderProcess")
.active()
.list();
for (ProcessInstance process : orderProcesses) {
processEngine.getRuntimeService().suspendProcessInstanceById(process.getId());
}
// 记录操作日志
auditLog("ORDER_PROCESSING_PAUSE", "ALL", "订单处理已暂停: " + userId);
}
}实施效果
- 订单取消处理时间从30分钟缩短到2分钟
- 系统维护期间零订单丢失
- 异常处理成功率提升至99.5%
- 客服满意度提升30%
案例二:某银行的信贷审批流程控制
某银行在信贷审批流程中实现了精细化的运行时控制:
合规要求
- 审批撤回:审批人员可以撤回错误的审批决定
- 流程跳转:特殊情况可以跳转到指定审批节点
- 状态监控:实时监控所有信贷流程状态
- 审计追踪:完整记录所有操作历史
技术方案
public class CreditApprovalController {
public void withdrawApproval(String taskId, String approverId, String reason) {
// 验证审批人员权限
if (!isTaskApprover(taskId, approverId)) {
throw new SecurityException("无权撤回审批: " + taskId);
}
// 检查撤回时间限制
if (!isWithinWithdrawalPeriod(taskId)) {
throw new ProcessEngineException("超出撤回时间限制");
}
// 执行撤回操作
TaskWithdrawManager withdrawManager = new TaskWithdrawManager();
withdrawManager.withdrawTaskWithPermissionCheck(taskId, approverId, reason);
// 发送通知
sendWithdrawalNotification(taskId, approverId, reason);
// 记录合规日志
complianceLog("APPROVAL_WITHDRAW", taskId, approverId, reason);
}
public void jumpToSpecificApprover(String processInstanceId,
String targetApprover,
String requesterId) {
// 验证请求者权限
if (!canRequestJump(requesterId, processInstanceId)) {
throw new SecurityException("无权请求流程跳转");
}
// 获取目标活动ID
String targetActivityId = getApproverActivityId(targetApprover);
// 执行跳转操作
ProcessInstanceJumper jumper = new ProcessInstanceJumper();
jumper.jumpToActivity(processInstanceId, targetActivityId);
// 记录合规日志
complianceLog("PROCESS_JUMP", processInstanceId, requesterId,
"跳转到审批人: " + targetApprover);
}
private boolean isTaskApprover(String taskId, String userId) {
Task task = processEngine.getTaskService().createTaskQuery()
.taskId(taskId)
.taskAssignee(userId)
.singleResult();
return task != null;
}
private boolean isWithinWithdrawalPeriod(String taskId) {
HistoricTaskInstance task = processEngine.getHistoryService()
.createHistoricTaskInstanceQuery()
.taskId(taskId)
.singleResult();
if (task == null || task.getEndTime() == null) {
return false;
}
// 检查是否在24小时内
long timeDiff = System.currentTimeMillis() - task.getEndTime().getTime();
return timeDiff <= 24 * 60 * 60 * 1000;
}
}业务效果
- 审批错误率降低至0.1%以下
- 合规审计通过率达到100%
- 审批效率提升25%
- 客户投诉率下降40%
未来发展趋势
智能化运行时控制
AI技术正在改变运行时控制的方式:
- 智能决策:基于机器学习自动决定流程控制操作
- 预测性控制:预测流程执行趋势并提前干预
- 自适应优化:根据执行情况自动优化控制策略
- 异常检测:智能检测流程执行异常并自动处理
无服务器化控制
Serverless架构为运行时控制带来新的可能性:
- 事件驱动:基于事件触发流程控制操作
- 按需执行:只在需要时执行控制逻辑
- 自动扩缩容:根据负载自动调整控制能力
- 成本优化:只为实际使用的控制操作付费
边缘计算控制
边缘计算为运行时控制提供分布式能力:
- 就近处理:在用户附近执行控制操作
- 断网处理:支持断网情况下的本地控制
- 数据同步:实现边缘和中心的控制状态同步
- 分布式管理:支持分布式的流程控制管理
结语
流程实例运行时控制是企业级BPM平台的核心功能,它为业务流程的灵活管理提供了强有力的技术支撑。通过深入理解启动、暂停、终止、跳转、撤回等核心操作的实现机制,以及权限控制、审计日志、性能优化等关键技术,我们可以构建出功能完善、安全可靠、性能优越的运行时控制系统。
在实际实施过程中,我们需要根据具体的业务需求和技术条件,选择合适的技术方案和实现策略,并持续优化和完善系统设计。同时,也要关注技术发展趋势,积极拥抱AI、Serverless、边缘计算等新技术,为企业的业务流程管理提供更加强大和灵活的技术支撑。
