# Flowable 6.8.1 实战:SpringBoot + H2 构建企业级请假审批系统
去年团队需要快速上线一个内部审批系统时,我第一次接触Flowable。当时用三天时间就搭建完成了原本预估两周的工作量,这种效率让我彻底爱上了这个工作流引擎。本文将带你从零开始,用SpringBoot和H2内存数据库构建一个完整的请假审批系统,包含流程设计、用户任务处理等核心功能。
1. 环境准备与项目初始化
在开始编码前,我们需要准备好开发环境。推荐使用IntelliJ IDEA作为开发工具,它能够很好地支持SpringBoot项目。
首先创建一个新的SpringBoot项目,在pom.xml中添加以下关键依赖:
org.flowable
flowable-spring-boot-starter
6.8.1
com.h2database
h2
runtime
org.projectlombok
lombok
true
在application.properties中配置H2数据库:
# H2配置 spring.datasource.url=jdbc:h2:mem:flowable-db;DB_CLOSE_DELAY=-1 spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= # Flowable配置 flowable.database-schema-update=true flowable.async-executor-activate=false
> 提示:H2是内存数据库,适合开发和测试环境。生产环境建议使用MySQL或PostgreSQL。
2. 流程设计与建模
请假审批流程通常包含以下步骤:
- 员工提交请假申请
- 部门主管审批
- 人事部门备案
- 流程结束
我们使用BPMN 2.0标准来定义这个流程。在resources/processes目录下创建leave-request.bpmn20.xml文件:
${approvalResult == 'approve'}
${approvalResult == 'reject'}
这个BPMN文件定义了一个完整的请假审批流程,包含:
- 三个用户任务节点
- 一个排他网关用于流程分支
- 表单字段定义
- 条件表达式
3. 用户与组管理
在Flowable中,用户和组的管理通过IdentityService实现。我们先创建一些测试用户和组:
@Service @RequiredArgsConstructor public class IdentitySetupService { private final IdentityService identityService; @PostConstruct public void init() { createUser("employee1", "张三", "", ""); createUser("manager1", "李经理", "", ""); createUser("hr1", "王人事", "", ""); createGroup("managers", "部门主管"); createGroup("hr", "人事部门"); identityService.createMembership("manager1", "managers"); identityService.createMembership("hr1", "hr"); } private void createUser(String userId, String userName, String email, String password) private void createGroup(String groupId, String groupName) }
4. 流程部署与启动
流程部署是将BPMN文件部署到Flowable引擎的过程。我们创建一个服务类来处理流程部署和启动:
@Service @RequiredArgsConstructor public class LeaveProcessService public String startProcess(String initiatorId, LeaveRequest request) @Data public static class LeaveRequest { private int days; private String reason; } }
5. 任务处理与流程推进
流程启动后,各节点任务需要被处理才能推进流程。我们创建一个任务处理服务:
@Service @RequiredArgsConstructor public class TaskService public List
getTasksForGroup(String groupId) { return flowableTaskService.createTaskQuery() .taskCandidateGroup(groupId) .list(); } public void completeSubmitTask(String taskId, LeaveRequest request) public void completeApprovalTask(String taskId, ApprovalResult result) public void completeHrTask(String taskId, String recordNo) { Map
variables = new HashMap<>(); variables.put("recordNo", recordNo); flowableTaskService.complete(taskId, variables); } @Data public static class ApprovalResult { private String result; // "approve" or "reject" private String comment; } }
6. 流程监控与历史查询
了解流程当前状态和历史记录对于系统管理非常重要:
@Service @RequiredArgsConstructor public class ProcessMonitorService public List
getProcessHistory(String processInstanceId) { return historyService.createHistoricActivityInstanceQuery() .processInstanceId(processInstanceId) .orderByHistoricActivityInstanceStartTime() .asc() .list(); } public Map
getProcessVariables(String processInstanceId) public ProcessInstance getProcessInstance(String processInstanceId) { return runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); } }
7. 构建REST API
最后,我们创建一些REST端点来暴露功能:
@RestController @RequestMapping("/api/leave") @RequiredArgsConstructor public class LeaveProcessController { private final LeaveProcessService leaveProcessService; private final TaskService taskService; private final ProcessMonitorService monitorService; @PostMapping("/start") public ResponseEntity
startProcess( @RequestBody LeaveProcessService.LeaveRequest request, @RequestParam String initiatorId) { String processId = leaveProcessService.startProcess(initiatorId, request); return ResponseEntity.ok(processId); } @GetMapping("/tasks/user/{userId}") public ResponseEntity
> getUserTasks(@PathVariable String userId) @GetMapping("/tasks/group/{groupId}") public ResponseEntity
> getGroupTasks(@PathVariable String groupId) @PostMapping("/complete/submit/{taskId}") public ResponseEntity
completeSubmitTask( @PathVariable String taskId, @RequestBody LeaveProcessService.LeaveRequest request) { taskService.completeSubmitTask(taskId, request); return ResponseEntity.ok().build(); } @PostMapping("/complete/approval/{taskId}") public ResponseEntity
completeApprovalTask( @PathVariable String taskId, @RequestBody TaskService.ApprovalResult result) { taskService.completeApprovalTask(taskId, result); return ResponseEntity.ok().build(); } @GetMapping("/history/{processInstanceId}") public ResponseEntity
> getProcessHistory( @PathVariable String processInstanceId) }
8. 系统测试与验证
现在我们可以测试整个流程了。首先部署流程:
@SpringBootTest class LeaveProcessTests { @Autowired private LeaveProcessService leaveProcessService; @Test void testDeployProcess() { leaveProcessService.deployProcess(); } }
然后模拟一个完整的请假审批流程:
@Test void testCompleteLeaveProcess()
9. 高级功能扩展
基础功能实现后,我们可以考虑添加一些高级功能:
9.1 邮件通知
@Service @RequiredArgsConstructor public class NotificationService } }
9.2 动态任务分配
public void setDynamicAssignee(String processInstanceId, String taskId, String assignee) }
9.3 流程版本控制
public List
getProcessVersions(String processKey) { return repositoryService.createProcessDefinitionQuery() .processDefinitionKey(processKey) .orderByProcessDefinitionVersion() .desc() .list(); }
10. 性能优化建议
在实际生产环境中,需要考虑以下优化点:
- 数据库连接池配置:
spring.datasource.hikari.maximum-pool-size=10 spring.datasource.hikari.minimum-idle=5 - 异步执行器配置:
flowable.async-executor-activate=true flowable.async-executor-core-pool-size=5 flowable.async-executor-max-pool-size=10 - 历史数据归档:
historyService.createHistoricProcessInstanceQuery() .finishedBefore(oneYearAgo) .delete(); - 缓存配置:
flowable.process-definition-cache-limit=100 flowable.process-model-cache-limit=50
11. 常见问题解决
在实际开发中,可能会遇到以下问题:
- 流程定义找不到:
- 检查BPMN文件是否在resources/processes目录下
- 确认文件后缀是.bpmn20.xml
- 检查流程定义key是否正确
- 任务分配失败:
- 确认用户已创建并分配了正确组
- 检查任务分配表达式语法
- 验证流程变量是否已正确设置
- 流程不推进:
- 检查网关条件表达式
- 验证任务是否已完成
- 查看ACT_RU_TASK表确认当前任务
- 性能问题:
- 检查数据库索引
- 考虑启用异步执行器
- 优化复杂网关条件
12. 生产环境建议
当系统准备上线时,应考虑以下方面:
- 数据库选择:
- 生产环境推荐MySQL或PostgreSQL
- 配置主从复制提高可用性
- 集群部署:
flowable.job-service-acquire-wait-time=10000 flowable.job-service-lock-wait-time=30000 - 监控集成:
- 使用Prometheus监控流程指标
- 配置Grafana仪表板
- 备份策略:
- 定期备份流程定义
- 导出重要流程实例数据
13. 与Ruoyi-Flowable集成
如果需要更完整的解决方案,可以考虑集成Ruoyi-Flowable:
- 功能对比:
| 功能 | 自定义实现 | Ruoyi-Flowable |
|---|---|---|
| 流程设计器 | 需要开发 | 内置 |
| 表单设计器 | 需要开发 | 内置 |
| 用户界面 | 需要开发 | 提供 |
| 权限管理 | 需要开发 | 内置 |
- 集成方式:
- 作为独立服务通过REST调用
- 嵌入到现有系统中
- 优势:
- 减少开发工作量
- 提供更完整的用户界面
- 内置更多企业级功能
14. **实践总结
经过多个项目的实践,我总结了以下**实践:
- 流程设计原则:
- 保持流程简单直观
- 合理使用子流程
- 避免过度复杂的网关条件
- 代码组织建议:
- 将流程相关代码集中管理
- 使用服务层封装Flowable API
- 实现统一的异常处理
- 性能关键点:
- 批量操作使用批量API
- 合理设置历史级别
- 定期清理历史数据
- 团队协作:
- 统一流程建模规范
- 版本控制BPMN文件
- 建立流程文档标准
15. 进一步学习资源
要深入学习Flowable,可以参考以下资源:
- 官方文档:
- Flowable用户手册
- BPMN 2.0规范
- 书籍推荐:
- 《Flowable流程引擎实战》
- 《BPMN 2.0标准指南》
- 社区资源:
- Flowable官方论坛
- GitHub开源项目
- 进阶主题:
- 流程事件监听
- 自定义行为注入
- 分布式流程引擎
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/255803.html