别再手动跑审批了!用Flowable工作流5分钟搞定一个发工资流程(附完整Java代码)
别再手动跑审批了!用Flowable工作流5分钟搞定发薪流程
每到发薪日,财务部门的同事总是忙得焦头烂额——纸质审批单在各部门间来回传递,一不小心就可能丢失;审批进度全靠人工跟进,效率低下还容易出错。作为技术负责人,你完全可以用Flowable工作流引擎,在一个下午内搭建出自动化发薪流程的原型。下面我们就从零开始,用最精简的代码实现"申请-审批-打款-通知"全流程自动化。
1. 五分钟搭建发薪流程骨架
1.1 绘制BPMN流程图
首先在Flowable Modeler中创建新模型,使用以下核心节点:
- 用户任务(User Task):用于财务审批环节
- 服务任务(Service Task):对接银行打款系统
- 中间信号捕获事件(Intermediate Catch Event):等待银行回调
- 排他网关(Exclusive Gateway):根据条件分流
流程图结构如下:
<process id="payrollProcess" name="薪资发放流程"> <startEvent id="start"/> <userTask id="financeApproval" name="财务审批"/> <serviceTask id="bankTransfer" name="银行打款"/> <intermediateCatchEvent id="waitCallback" name="等待银行回调"> <signalEventDefinition signalRef="bankSignal"/> </intermediateCatchEvent> <endEvent id="end"/> <!-- 省略序列流和网关细节 --> </process>1.2 关键配置速查表
| 配置项 | 值 | 作用 |
|---|---|---|
| 流程标识 | payrollProcess | 流程唯一标识 |
| 审批变量 | ${approval} | 存储审批结果 |
| 打款变量 | ${payment} | 存储银行返回状态 |
| 审批人变量 | ${assignee} | 动态指定审批人 |
| 信号引用 | bankSignal | 银行回调信号 |
2. 核心代码实现
2.1 动态审批人指派
启动流程时注入审批人变量:
public String startPayrollProcess(String applicantId, String financeApprover) { Map<String, Object> variables = new HashMap<>(); variables.put("assignee", financeApprover); // 动态指定审批人 variables.put("applicant", applicantId); ProcessInstance instance = runtimeService .startProcessInstanceByKey("payrollProcess", variables); return instance.getId(); }2.2 银行打款服务任务
实现JavaDelegate接口处理打款逻辑:
public class BankTransferDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { String businessKey = execution.getProcessInstanceBusinessKey(); // 模拟调用银行API PaymentResult result = mockBankAPI(businessKey); // 暂存交易流水号 execution.setVariable("transactionId", result.getTransactionId()); } private PaymentResult mockBankAPI(String businessKey) { // 实际项目替换为真实银行接口调用 return new PaymentResult(UUID.randomUUID().toString()); } }2.3 银行回调处理
银行处理完成后触发信号事件:
public void handleBankCallback(String businessKey, boolean success) { ProcessInstance instance = runtimeService .createProcessInstanceQuery() .processInstanceBusinessKey(businessKey) .singleResult(); if (instance != null) { runtimeService.signalEventReceived( "bankSignal", instance.getId(), Collections.singletonMap("payment", success ? "success" : "fail") ); } }3. 实战优化技巧
3.1 审批自动超时处理
在BPMN中添加定时边界事件:
<boundaryEvent id="timeoutEvent" attachedToRef="financeApproval"> <timerEventDefinition> <timeDuration>PT24H</timeDuration> </timerEventDefinition> </boundaryEvent>3.2 多级审批配置
使用监听器动态设置审批链:
public class MultiLevelApprovalListener implements TaskListener { @Override public void notify(DelegateTask task) { if ("financeApproval".equals(task.getTaskDefinitionKey())) { // 根据金额决定审批层级 Double amount = (Double) task.getVariable("amount"); if (amount > 100000) { task.addCandidateGroup("seniorFinance"); } else { task.setAssignee((String) task.getVariable("assignee")); } } } }4. 生产环境注意事项
- 事务管理:服务任务中涉及数据库操作时添加
@Transactional注解 - 异常处理:实现
FlowableExceptionHandler统一处理流程异常 - 性能优化:高频流程建议启用异步执行
<serviceTask id="asyncTask" flowable:async="true" flowable:exclusive="false"/>实际项目中,我们曾用这套方案将某企业发薪流程从平均3天缩短到4小时内完成。关键在于保持流程模型的简洁,把复杂逻辑放到外部服务中实现。
