Spring Boot 2.x 整合 Activiti 7 工作流引擎:从零搭建一个请假审批Demo
·
Spring Boot 2.x 整合 Activiti 7 工作流引擎:从零搭建一个请假审批Demo
在微服务架构盛行的今天,如何将传统的工作流引擎与现代开发框架无缝整合,成为许多企业级应用开发的关键挑战。Activiti 7作为新一代BPMN 2.0规范的实现,通过与Spring Boot 2.x的深度集成,为开发者提供了更简洁的配置方式和更强大的流程管理能力。本文将以一个真实的"员工请假-部门审批"业务场景为例,带你从零开始构建完整的解决方案。
1. 环境准备与项目初始化
1.1 创建Spring Boot项目
使用Spring Initializr快速生成项目骨架,选择以下核心依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
1.2 数据库配置
在application.yml中配置数据源和Activiti参数:
spring:
datasource:
url: jdbc:mysql://localhost:3306/activiti_demo?useSSL=false&serverTimezone=UTC
username: root
password: yourpassword
driver-class-name: com.mysql.cj.jdbc.Driver
activiti:
database-schema-update: true
history-level: full
async-executor-activate: false
关键配置说明:
database-schema-update: 设置为true时自动创建表结构history-level: 控制历史记录保存级别async-executor-activate: 是否启用异步任务执行
2. 流程设计与建模
2.1 使用BPMN设计请假流程
在resources/processes目录下创建leave-request.bpmn20.xml文件:
<bpmn2:definitions>
<bpmn2:process id="leaveProcess" name="员工请假流程">
<bpmn2:startEvent id="startEvent" />
<bpmn2:userTask id="applyLeave" name="提交请假申请"
activiti:assignee="${applicant}" />
<bpmn2:userTask id="managerApprove" name="经理审批"
activiti:assignee="${approver}" />
<bpmn2:exclusiveGateway id="decisionGateway" />
<bpmn2:endEvent id="endEvent" />
<!-- 流程连线定义 -->
<bpmn2:sequenceFlow sourceRef="startEvent" targetRef="applyLeave" />
<bpmn2:sequenceFlow sourceRef="applyLeave" targetRef="managerApprove" />
<bpmn2:sequenceFlow sourceRef="managerApprove" targetRef="decisionGateway" />
<bpmn2:sequenceFlow sourceRef="decisionGateway" targetRef="endEvent">
<bpmn2:conditionExpression xsi:type="tFormalExpression">
${approvalResult == true}
</bpmn2:conditionExpression>
</bpmn2:sequenceFlow>
</bpmn2:process>
</bpmn2:definitions>
2.2 流程变量设计
为请假流程定义关键变量:
| 变量名 | 类型 | 描述 |
|---|---|---|
| applicant | String | 申请人ID |
| approver | String | 审批人ID |
| startDate | Date | 请假开始日期 |
| endDate | Date | 请假结束日期 |
| reason | String | 请假原因 |
| approvalResult | Boolean | 审批结果 |
3. 业务逻辑实现
3.1 创建请假服务层
@Service
@RequiredArgsConstructor
public class LeaveService {
private final RuntimeService runtimeService;
private final TaskService taskService;
public String startLeaveProcess(LeaveRequest request) {
Map<String, Object> variables = new HashMap<>();
variables.put("applicant", request.getApplicant());
variables.put("approver", request.getApprover());
variables.put("startDate", request.getStartDate());
variables.put("endDate", request.getEndDate());
variables.put("reason", request.getReason());
ProcessInstance instance = runtimeService.startProcessInstanceByKey(
"leaveProcess", variables);
return instance.getId();
}
public List<Task> getUserTasks(String userId) {
return taskService.createTaskQuery()
.taskAssignee(userId)
.list();
}
public void completeTask(String taskId, boolean approved) {
Map<String, Object> variables = new HashMap<>();
variables.put("approvalResult", approved);
taskService.complete(taskId, variables);
}
}
3.2 构建REST API接口
@RestController
@RequestMapping("/api/leave")
@RequiredArgsConstructor
public class LeaveController {
private final LeaveService leaveService;
@PostMapping
public ResponseEntity<String> applyLeave(@RequestBody LeaveRequest request) {
String processId = leaveService.startLeaveProcess(request);
return ResponseEntity.ok("流程已启动,ID: " + processId);
}
@GetMapping("/tasks")
public ResponseEntity<List<Task>> getTasks(@RequestParam String userId) {
return ResponseEntity.ok(leaveService.getUserTasks(userId));
}
@PostMapping("/approve")
public ResponseEntity<String> approveTask(
@RequestParam String taskId,
@RequestParam boolean approved) {
leaveService.completeTask(taskId, approved);
return ResponseEntity.ok("任务处理完成");
}
}
4. 流程监控与管理
4.1 历史数据查询
@Service
@RequiredArgsConstructor
public class ProcessHistoryService {
private final HistoryService historyService;
public List<HistoricProcessInstance> getCompletedProcesses() {
return historyService.createHistoricProcessInstanceQuery()
.finished()
.list();
}
public List<HistoricActivityInstance> getProcessActivities(String processId) {
return historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processId)
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
}
}
4.2 流程可视化
利用Activiti提供的REST API获取流程图:
@GetMapping(value = "/diagram/{processId}", produces = MediaType.IMAGE_PNG_VALUE)
public byte[] getProcessDiagram(@PathVariable String processId) throws IOException {
ProcessInstance pi = runtimeService.createProcessInstanceQuery()
.processInstanceId(processId)
.singleResult();
BpmnModel model = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
InputStream diagram = new DefaultProcessDiagramGenerator()
.generateDiagram(model, "png", runtimeService.getActiveActivityIds(pi.getId()));
return IOUtils.toByteArray(diagram);
}
5. 高级配置与优化
5.1 自定义用户任务监听器
@Component
public class LeaveTaskListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
if ("managerApprove".equals(delegateTask.getTaskDefinitionKey())) {
// 发送审批通知
String message = String.format(
"您有一条来自%s的请假申请待审批",
delegateTask.getVariable("applicant"));
System.out.println(message);
}
}
}
5.2 异步执行器配置
在application.yml中启用异步执行:
activiti:
async-executor-activate: true
async-executor-core-pool-size: 5
async-executor-max-pool-size: 10
async-executor-queue-capacity: 100
5.3 性能优化建议
-
流程实例缓存 :配置流程引擎缓存策略
@Bean public ProcessEngineConfiguration processEngineConfiguration( DataSource dataSource, PlatformTransactionManager transactionManager) { SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration(); config.setDataSource(dataSource); config.setTransactionManager(transactionManager); config.setDatabaseSchemaUpdate("true"); config.setAsyncExecutorActivate(true); config.setProcessDefinitionCacheLimit(100); return config; } -
批量操作 :对于大量任务处理使用批量API
taskService.createTaskQuery() .taskAssignee("user1") .listPage(0, 100) .forEach(task -> taskService.complete(task.getId())); -
历史数据归档 :定期归档历史数据减少主表压力
6. 常见问题排查
6.1 流程无法启动
检查步骤:
- 确认流程定义已正确部署
repositoryService.createProcessDefinitionQuery() .processDefinitionKey("leaveProcess") .list(); - 验证必要流程变量是否设置
- 检查Activiti自动配置日志
6.2 任务分配异常
典型解决方案:
- 确保assignee变量已正确设置
- 实现自定义任务分配逻辑
taskService.setAssignee(taskId, newAssignee);
6.3 性能瓶颈处理
监控指标:
ManagementService managementService = processEngine.getManagementService();
TablePage tablePage = managementService.createTablePageQuery()
.tableName("ACT_RU_TASK")
.listPage(0, 100);
优化方向:
- 增加异步执行器线程池
- 优化数据库索引
- 拆分复杂流程为子流程
7. 安全与权限控制
7.1 集成Spring Security
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/leave/**").authenticated()
.and()
.httpBasic();
}
}
7.2 流程数据权限过滤
taskService.createTaskQuery()
.taskCandidateOrAssigned(userId)
.list();
7.3 敏感数据保护
对流程变量进行加密处理:
variables.put("reason", encryptService.encrypt(reason));
8. 测试策略
8.1 单元测试配置
@SpringBootTest
@ActivitiTest
public class LeaveProcessTest {
@Autowired
private RuntimeService runtimeService;
@Test
public void testLeaveProcess() {
// 测试流程启动和任务分配
Map<String, Object> vars = new HashMap<>();
vars.put("applicant", "user1");
vars.put("approver", "manager1");
ProcessInstance instance = runtimeService
.startProcessInstanceByKey("leaveProcess", vars);
assertNotNull(instance);
}
}
8.2 集成测试要点
测试场景覆盖:
- 正常审批流程
- 审批拒绝路径
- 多实例并发处理
- 超时自动处理
8.3 性能测试建议
使用JMeter模拟:
- 并发流程启动
- 批量任务处理
- 长时间运行流程监控
9. 部署与运维
9.1 Docker容器化部署
示例Dockerfile:
FROM openjdk:11-jre
COPY target/leave-app.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
9.2 数据库迁移策略
使用Liquibase管理数据库变更:
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
9.3 监控端点配置
启用Actuator端点:
management:
endpoints:
web:
exposure:
include: health,info,activiti
10. 扩展与定制
10.1 自定义表单集成
集成方案选择:
- 直接使用流程变量
- 关联外部表单数据
- 实现动态表单引擎
10.2 多租户支持
配置多数据源策略:
@Bean
public MultiTenantProcessEngineConfiguration processEngineConfiguration() {
MultiTenantProcessEngineConfiguration config = new MultiTenantProcessEngineConfiguration();
config.setTenantConfigurator(new CustomTenantConfigurator());
return config;
}
10.3 移动端适配
构建轻量级API:
@GetMapping("/mobile/tasks")
public List<MobileTask> getMobileTasks(@RequestParam String userId) {
return taskService.createTaskQuery()
.taskAssignee(userId)
.list()
.stream()
.map(this::convertToMobileTask)
.collect(Collectors.toList());
}
更多推荐




所有评论(0)