别再手动写审批逻辑了!用SpringBoot+Activiti工作流引擎,5步搞定业务流程自动化
2026/4/28 5:27:21 网站建设 项目流程

告别繁琐审批代码:SpringBoot+Activiti工作流引擎实战指南

每次接到审批流程需求时,你是否也经历过这样的痛苦?先要设计状态字段,再编写各种条件判断,最后还要处理复杂的流转逻辑。更可怕的是业务规则一变,整个代码就要推倒重来。今天我要分享的这套技术组合,能让你用1/10的代码量实现更灵活的流程控制。

1. 为什么我们需要工作流引擎

三年前我接手过一个采购审批系统,当时用纯代码实现了多级审批逻辑。当业务从"部门经理→财务"变成"部门经理→总监→财务"时,我不得不通宵重写了87%的审批相关代码。这种经历让我意识到:用代码硬编码业务流程是条死胡同

传统审批代码的三大痛点:

  1. 状态爆炸:每个审批节点都需要维护状态字段,5个节点的流程就可能产生32种状态组合
  2. 逻辑耦合:审批规则与业务代码深度绑定,简单调整就要全量测试
  3. 历史追溯难:需要额外开发日志系统记录流程轨迹

而工作流引擎通过流程定义与执行分离的架构,完美解决了这些问题。以请假流程为例:

实现方式代码量修改成本可维护性
传统编码500行+
Activiti50行优秀

2. Activiti核心架构解析

Activiti的聪明之处在于它用BPMN 2.0标准将流程可视化。开发时只需关注三要素:

  1. 流程定义:用图形化工具设计的.bpmn文件
  2. 流程实例:每次业务发起的运行时实例
  3. 任务节点:需要人工处理的环节

其数据库设计也非常精巧:

ACT_RE_* -- 存储流程定义等静态资源 ACT_RU_* -- 运行时的任务、变量等 ACT_HI_* -- 历史数据用于审计 ACT_GE_* -- 通用数据如二进制资源

提示:生产环境建议关闭自动建表功能,通过database-schema-update: false显式控制

3. 五步实现请假审批自动化

3.1 环境准备

在SpringBoot项目中添加依赖:

<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifactId> <version>7.1.0.M6</version> </dependency>

配置参数示例:

spring: activiti: database-schema-update: true db-history-used: true history-level: full check-process-definitions: true

3.2 流程设计

使用Activiti Modeler设计请假流程:

  1. 开始事件 → 2. 员工提交 → 3. 经理审批 → 4. HR备案 → 5. 结束事件

关键网关配置技巧:

  • 排他网关:用于条件分支(如请假天数>3天需总监审批)
  • 并行网关:适用于会签场景(如多部门联合审批)

3.3 流程部署

将设计好的bpmn文件部署到引擎:

@Autowired private RepositoryService repositoryService; public void deploy() { Deployment deployment = repositoryService.createDeployment() .addClasspathResource("processes/leave.bpmn") .name("请假流程") .deploy(); log.info("部署ID: {}", deployment.getId()); }

3.4 启动流程实例

关联业务数据启动流程:

public String startLeaveProcess(Long leaveId, String userId) { Map<String, Object> variables = new HashMap<>(); variables.put("leaveId", leaveId); ProcessInstance instance = runtimeService.startProcessInstanceByKey( "leaveProcess", leaveId.toString(), variables ); return instance.getId(); }

3.5 任务处理

查询待办任务的典型实现:

public List<TaskDTO> getTasks(String assignee) { return taskService.createTaskQuery() .taskAssignee(assignee) .list() .stream() .map(task -> { TaskDTO dto = new TaskDTO(); dto.setTaskId(task.getId()); dto.setName(task.getName()); // 获取业务关联ID dto.setBusinessKey(runtimeService .createProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult() .getBusinessKey()); return dto; }).collect(Collectors.toList()); }

审批操作示例:

public void approveTask(String taskId, boolean approved) { Map<String, Object> variables = new HashMap<>(); variables.put("approved", approved); taskService.complete(taskId, variables); }

4. 高级实战技巧

4.1 动态指派审批人

在bpmn中使用表达式动态指定处理人:

<userTask id="managerApproval" name="经理审批" activiti:assignee="${leaveService.getManager(applyUserId)}"/>

对应的Java方法:

public String getManager(String employeeId) { // 从组织架构查询直属上级 return orgMapper.selectManagerByEmp(employeeId); }

4.2 流程版本控制

当流程需要升级时,新部署会自动生成新版本:

long count = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("leaveProcess") .count(); // 获取最新版本 ProcessDefinition definition = repositoryService .createProcessDefinitionQuery() .processDefinitionKey("leaveProcess") .latestVersion() .singleResult();

4.3 流程监控看板

获取流程实时状态:

ProcessInstance instance = runtimeService .createProcessInstanceQuery() .processInstanceId(instanceId) .singleResult(); // 获取当前活动节点 List<String> activeActivityIds = runtimeService .getActiveActivityIds(instance.getId());

4.4 业务关联查询

通过BusinessKey关联业务数据:

public LeaveDetail getLeaveByInstance(String instanceId) { ProcessInstance instance = runtimeService .createProcessInstanceQuery() .processInstanceId(instanceId) .singleResult(); return leaveMapper.selectById( Long.parseLong(instance.getBusinessKey()) ); }

5. 性能优化方案

5.1 历史数据归档

对于完成流程的历史数据:

-- 定期执行归档 INSERT INTO ACT_HI_*_ARCHIVE SELECT * FROM ACT_HI_* WHERE END_TIME_ < DATE_SUB(NOW(), INTERVAL 3 MONTH); DELETE FROM ACT_HI_* WHERE END_TIME_ < DATE_SUB(NOW(), INTERVAL 3 MONTH);

5.2 异步任务处理

配置邮件通知等异步任务:

<serviceTask id="sendMail" activiti:class="com.example.AsyncMailDelegate" activiti:async="true"/>

对应的委托类:

public class AsyncMailDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { // 发送邮件逻辑 } }

5.3 缓存优化

对频繁查询的流程定义启用缓存:

@Cacheable(value = "processDefinition", key = "#processDefinitionKey") public ProcessDefinition getLatestDefinition(String processDefinitionKey) { return repositoryService.createProcessDefinitionQuery() .processDefinitionKey(processDefinitionKey) .latestVersion() .singleResult(); }

在最近的一个供应链系统中,我们通过Activiti重构了原本2000多行的审批代码。现在业务人员可以自行调整审批路线,再也不用求着开发改代码了。最让我惊喜的是,当我们需要添加风控审批环节时,只用了15分钟修改流程图就完成了变更。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询