Activiti 7.x实战:构建带撤回与驳回功能的智能审批流
当我们需要在Java应用中实现复杂的审批流程时,Activiti作为一款轻量级的工作流引擎,提供了强大的流程控制能力。本文将从一个真实的报销审批场景出发,逐步构建一个具备撤回、驳回和挂起功能的完整流程解决方案。
1. 环境准备与基础流程搭建
在开始之前,我们需要准备以下环境:
- JDK 1.8+
- Spring Boot 2.5.x
- Activiti 7.1.0
- MySQL 5.7+
首先创建一个Spring Boot项目并添加Activiti依赖:
xml复制<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0</version>
</dependency>
基础报销流程的BPMN定义如下:
xml复制<process id="expense_approval" name="员工报销审批流程">
<startEvent id="startEvent" />
<userTask id="submitExpense" name="提交报销" activiti:assignee="${applicant}" />
<userTask id="deptManagerApprove" name="部门经理审批" activiti:assignee="deptManager" />
<userTask id="financeApprove" name="财务审批" activiti:assignee="financeStaff" />
<endEvent id="endEvent" />
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitExpense" />
<sequenceFlow id="flow2" sourceRef="submitExpense" targetRef="deptManagerApprove" />
<sequenceFlow id="flow3" sourceRef="deptManagerApprove" targetRef="financeApprove" />
<sequenceFlow id="flow4" sourceRef="financeApprove" targetRef="endEvent" />
</process>
这个简单的流程定义了三个审批节点:员工提交、部门经理审批和财务审批。接下来我们需要为这个基础流程添加更智能的控制功能。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 实现流程撤回功能
在实际业务中,员工提交报销后可能发现填写错误,需要在部门经理审批前撤回申请。Activiti本身不直接提供撤回功能,但我们可以通过API组合实现。
撤回功能的实现原理:
- 检查当前流程实例状态
- 验证当前用户是否有权撤回
- 修改流程实例的当前节点
- 清理或保留相关历史记录
以下是核心实现代码:
java复制public class ProcessRecallService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
public boolean recallProcess(String processInstanceId, String userId) {
// 获取当前任务
Task currentTask = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.singleResult();
// 验证用户权限
HistoricTaskInstance submitTask = historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.taskDefinitionKey("submitExpense")
.taskAssignee(userId)
.singleResult();
if(submitTask == null) {
throw new IllegalStateException("只有提交人才能撤回申请");
}
// 修改流程定义
BpmnModel bpmnModel = repositoryService.getBpmnModel(
runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult()
.getProcessDefinitionId());
// 实现流程跳转逻辑
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(processInstanceId)
.moveActivityIdTo(currentTask.getTaskDefinitionKey(), "submitExpense")
.changeState();
// 添加撤回备注
taskService.addComment(currentTask.getId(), processInstanceId,
"申请已由" + userId + "撤回");
return true;
}
}
前端交互建议:
javascrip复制
