Flowable工作流:从入门到实战
一、什么是Flowable
Flowable是一个开源的轻量级业务流程引擎(BPMN 2.0),它起源于Activiti项目,是Activiti的继任者。Flowable提供了完整的工作流和业务流程管理(BPM)平台,支持流程定义、部署、执行、监控等全生命周期管理。
1.1 核心特性
- BPMN 2.0标准支持:完全符合BPMN 2.0规范
- 轻量级:可嵌入到任何Java应用中
- 高性能:支持高并发场景
- 灵活扩展:提供丰富的扩展点
- 云原生:支持微服务架构
1.2 核心组件
Flowable主要由以下核心组件构成:
- Flowable Engine:核心流程引擎
- Flowable Modeler:流程建模工具
- Flowable Task:任务管理应用
- Flowable Admin:管理监控界面
- Flowable REST:REST API接口
二、核心概念详解
2.1 BPMN 2.0基础
BPMN(Business Process Model and Notation)是业务流程建模与 notation 的标准。BPMN 2.0定义了一套标准的图形符号来表示业务流程。
基本元素
- 事件(Event):流程中发生的事情,如开始事件、结束事件
- 活动(Activity):流程中的工作单元,如用户任务、服务任务
- 网关(Gateway):控制流程分支,如排他网关、并行网关
- 连接线(Sequence Flow):连接各个元素
2.2 流程定义
流程定义是业务流程的静态描述,使用BPMN XML格式定义。一个典型的请假流程定义如下:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
targetNamespace="Examples">
<process id="leaveRequest" name="请假流程" isExecutable="true">
<!-- 开始事件 -->
<startEvent id="startEvent" name="开始"/>
<!-- 员工填写请假单 -->
<userTask id="employeeTask" name="填写请假单"
flowable:assignee="${employee}"/>
<!-- 部门经理审批 -->
<userTask id="managerTask" name="经理审批"
flowable:candidateGroups="managers"/>
<!-- 排他网关:根据天数决定是否需要HR审批 -->
<exclusiveGateway id="gateway"/>
<!-- HR审批(超过3天需要) -->
<userTask id="hrTask" name="HR审批"
flowable:candidateGroups="hr"/>
<!-- 结束事件 -->
<endEvent id="endEvent" name="结束"/>
<!-- 连接线 -->
<sequenceFlow sourceRef="startEvent" targetRef="employeeTask"/>
<sequenceFlow sourceRef="employeeTask" targetRef="managerTask"/>
<sequenceFlow sourceRef="managerTask" targetRef="gateway"/>
<sequenceFlow sourceRef="gateway" targetRef="hrTask">
<conditionExpression>${days > 3}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="gateway" targetRef="endEvent">
<conditionExpression>${days <= 3}</conditionExpression>
</sequenceFlow>
<sequenceFlow sourceRef="hrTask" targetRef="endEvent"/>
</process>
</definitions>
2.3 流程实例与执行
流程实例是流程定义的一次具体执行。一个流程定义可以创建多个流程实例,每个实例有独立的执行状态和变量。
三、快速入门
3.1 环境搭建
首先创建Maven项目,添加Flowable依赖:
<dependencies>
<!-- Flowable核心引擎 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>7.0.0</version>
</dependency>
<!-- Flowable REST API -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-rest</artifactId>
<version>7.0.0</version>
</dependency>
<!-- 数据库连接 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.224</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
</dependency>
</dependencies>
3.2 初始化流程引擎
public class FlowableEngineConfig {
private static ProcessEngine processEngine;
public static ProcessEngine getProcessEngine() {
if (processEngine == null) {
synchronized (FlowableEngineConfig.class) {
if (processEngine == null) {
// 配置流程引擎
ProcessEngineConfiguration configuration = ProcessEngineConfiguration
.createStandaloneProcessEngineConfiguration();
// 配置数据库连接
configuration.setJdbcDriver("org.h2.Driver");
configuration.setJdbcUrl("jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1");
configuration.setJdbcUsername("sa");
configuration.setJdbcPassword("");
// 自动创建/更新数据库表结构
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
// 创建流程引擎
processEngine = configuration.buildProcessEngine();
}
}
}
return processEngine;
}
// 获取各个服务
public static RepositoryService getRepositoryService() {
return getProcessEngine().getRepositoryService();
}
public static RuntimeService getRuntimeService() {
return getProcessEngine().getRuntimeService();
}
public static TaskService getTaskService() {
return getProcessEngine().getTaskService();
}
public static HistoryService getHistoryService() {
return getProcessEngine().getHistoryService();
}
public static ManagementService getManagementService() {
return getProcessEngine().getManagementService();
}
}
3.3 部署流程定义
public class ProcessDeploymentService {
/**
* 部署流程定义
*/
public String deployProcess(String processName, String resourcePath) {
Deployment deployment = FlowableEngineConfig.getRepositoryService()
.createDeployment()
.name(processName)
.addClasspathResource(resourcePath)
.deploy();
System.out.println("流程部署成功,部署ID: " + deployment.getId());
return deployment.getId();
}
/**
* 查询已部署的流程列表
*/
public List<ProcessDefinition> listProcesses() {
return FlowableEngineConfig.getRepositoryService()
.createProcessDefinitionQuery()
.orderByProcessDefinitionName()
.asc()
.list();
}
}
3.4 启动流程实例
public class ProcessInstanceService {
/**
* 启动流程实例
*/
public ProcessInstance startProcess(String processDefinitionKey, Map<String, Object> variables) {
ProcessInstance processInstance = FlowableEngineConfig.getRuntimeService()
.startProcessInstanceByKey(processDefinitionKey, variables);
System.out.println("流程实例启动成功,实例ID: " + processInstance.getId());
System.out.println("业务Key: " + processInstance.getBusinessKey());
return processInstance;
}
/**
* 查询运行中的流程实例
*/
public List<ProcessInstance> listRunningInstances() {
return FlowableEngineConfig.getRuntimeService()
.createProcessInstanceQuery()
.orderByStartTime()
.desc()
.list();
}
}
四、核心服务详解
Flowable通过服务层对外提供功能,主要包括以下服务:
4.1 RepositoryService(仓库服务)
管理流程定义和部署对象:
// 部署流程
Deployment deployment = repositoryService.createDeployment()
.name("请假流程")
.addClasspathResource("processes/leave-request.bpmn20.xml")
.deploy();
// 查询流程定义
ProcessDefinition processDefinition = repositoryService
.createProcessDefinitionQuery()
.processDefinitionKey("leaveRequest")
.singleResult();
// 挂起/激活流程定义
repositoryService.suspendProcessDefinitionById(processDefinitionId);
repositoryService.activateProcessDefinitionById(processDefinitionId);
// 删除流程定义
repositoryService.deleteDeployment(deploymentId, true);
4.2 RuntimeService(运行时服务)
管理流程实例和执行:
// 启动流程实例
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("leaveRequest", variables);
// 设置流程变量
runtimeService.setVariable(processInstanceId, "days", 5);
runtimeService.setVariable(processInstanceId, "reason", "休息");
// 获取流程变量
Integer days = (Integer) runtimeService.getVariable(processInstanceId, "days");
// 触发流程执行
runtimeService.trigger(executionId);
// 挂起/激活流程实例
runtimeService.suspendProcessInstanceById(processInstanceId);
runtimeService.activateProcessInstanceById(processInstanceId);
// 删除流程实例
runtimeService.deleteProcessInstance(processInstanceId, "取消申请");
4.3 TaskService(任务服务)
管理用户任务:
// 查询用户的待办任务
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("zhangsan")
.orderByTaskCreateTime()
.desc()
.list();
// 完成任务
taskService.complete(taskId);
// 带变量完成任务
Map<String, Object> variables = new HashMap<>();
variables.put("approved", true);
taskService.complete(taskId, variables);
// 认领任务(候选任务)
taskService.claim(taskId, "lisi");
// 委派任务
taskService.delegateTask(taskId, "wangwu");
// 设置任务优先级
taskService.setPriority(taskId, 50);
4.4 HistoryService(历史服务)
查询历史数据:
// 查询已完成的流程实例
List<HistoricProcessInstance> finishedInstances = historyService
.createHistoricProcessInstanceQuery()
.finished()
.orderByProcessInstanceEndTime()
.desc()
.list();
// 查询历史任务
List<HistoricTaskInstance> historicTasks = historyService
.createHistoricTaskInstanceQuery()
.taskAssignee("zhangsan")
.finished()
.list();
// 查询历史变量
List<HistoricVariableInstance> variables = historyService
.createHistoricVariableInstanceQuery()
.processInstanceId(processInstanceId)
.list();
// 查询流程实例历史(按时间线)
List<HistoricActivityInstance> activities = historyService
.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
.orderByHistoricActivityInstanceStartTime()
.asc()
.list();
4.5 ManagementService(管理服务)
执行管理操作:
// 获取数据库表信息
TableMetaData tableMetaData = managementService
.getTablesMetaData()
.get("ACT_RU_TASK");
// 执行自定义SQL
List<Map<String, Object>> results = managementService
.executeCustomSql(
new AbstractCustomSqlExecution<CustomQuery, List<Map<String, Object>>>(CustomQuery.class) {
@Override
public List<Map<String, Object>> execute(Configuration configuration) {
// 自定义SQL执行逻辑
return null;
}
}
);
// 获取作业列表
List<Job> jobs = managementService.createJobQuery().list();
五、实战案例:请假审批系统
5.1 业务需求
实现一个企业内部请假审批系统,支持以下功能:
- 员工提交请假申请
- 部门经理审批(1-3天直接通过)
- HR审批(超过3天需要HR审批)
- 审批通过/驳回
- 查询请假记录
5.2 系统架构设计
5.3 流程定义
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:flowable="http://flowable.org/bpmn"
targetNamespace="Examples">
<process id="leaveRequest" name="请假审批流程" isExecutable="true">
<!-- 开始事件 -->
<startEvent id="startEvent" name="提交申请"/>
<!-- 员工填写请假单 -->
<userTask id="submitLeave" name="填写请假单"
flowable:assignee="${initiator}">
<documentation>员工填写请假信息,包括请假天数、原因等</documentation>
</userTask>
<!-- 部门经理审批 -->
<userTask id="managerApproval" name="经理审批"
flowable:candidateGroups="managers">
<documentation>部门经理审批请假申请</documentation>
</userTask>
<!-- 排他网关:根据审批结果和天数决定流程走向 -->
<exclusiveGateway id="approvalGateway"/>
<!-- 驳回处理 -->
<serviceTask id="rejectHandler" name="处理驳回"
flowable:class="com.example.flowable.delegate.RejectDelegate"/>
<!-- HR审批(超过3天) -->
<userTask id="hrApproval" name="HR审批"
flowable:candidateGroups="hr">
<documentation>HR审批长期请假申请</documentation>
</userTask>
<!-- 通知员工 -->
<serviceTask id="notifyEmployee" name="发送通知"
flowable:class="com.example.flowable.delegate.NotifyDelegate"/>
<!-- 结束事件 -->
<endEvent id="approveEnd" name="审批通过"/>
<endEvent id="rejectEnd" name="审批驳回"/>
<!-- 连接线 -->
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitLeave"/>
<sequenceFlow id="flow2" sourceRef="submitLeave" targetRef="managerApproval"/>
<sequenceFlow id="flow3" sourceRef="managerApproval" targetRef="approvalGateway"/>
<!-- 驳回 -->
<sequenceFlow id="flow4" sourceRef="approvalGateway" targetRef="rejectHandler">
<conditionExpression>${approved == false}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow5" sourceRef="rejectHandler" targetRef="notifyEmployee"/>
<sequenceFlow id="flow6" sourceRef="notifyEmployee" targetRef="rejectEnd"/>
<!-- 通过但需要HR审批 -->
<sequenceFlow id="flow7" sourceRef="approvalGateway" targetRef="hrApproval">
<conditionExpression>${approved == true && days > 3}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow8" sourceRef="hrApproval" targetRef="notifyEmployee"/>
<sequenceFlow id="flow9" sourceRef="notifyEmployee" targetRef="approveEnd"/>
<!-- 通过且不需要HR审批 -->
<sequenceFlow id="flow10" sourceRef="approvalGateway" targetRef="notifyEmployee">
<conditionExpression>${approved == true && days <= 3}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow11" sourceRef="notifyEmployee" targetRef="approveEnd"/>
</process>
</definitions>
5.4 服务层实现
请假服务
@Service
public class LeaveRequestService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
/**
* 创建请假申请
*/
public LeaveRequest createLeaveRequest(LeaveRequest request) {
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("initiator", request.getEmployeeId());
variables.put("days", request.getDays());
variables.put("reason", request.getReason());
variables.put("startDate", request.getStartDate());
variables.put("endDate", request.getEndDate());
// 启动流程实例
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey("leaveRequest", request.getBusinessKey(), variables);
// 完成填写请假单任务,自动流转到经理审批
Task task = taskService.createTaskQuery()
.processInstanceId(processInstance.getId())
.taskAssignee(request.getEmployeeId())
.singleResult();
if (task != null) {
taskService.complete(task.getId());
}
// 保存流程实例ID
request.setProcessInstanceId(processInstance.getId());
request.setStatus("pending");
return request;
}
/**
* 经理审批
*/
public void managerApproval(String taskId, boolean approved, String comment) {
Map<String, Object> variables = new HashMap<>();
variables.put("approved", approved);
variables.put("managerComment", comment);
// 添加审批意见
taskService.addComment(taskId, null, comment);
// 完成任务
taskService.complete(taskId, variables);
}
/**
* HR审批
*/
public void hrApproval(String taskId, boolean approved, String comment) {
Map<String, Object> variables = new HashMap<>();
variables.put("approved", approved);
variables.put("hrComment", comment);
taskService.addComment(taskId, null, comment);
taskService.complete(taskId, variables);
}
/**
* 获取用户的待办任务
*/
public List<TaskDTO> getMyTasks(String userId) {
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee(userId)
.orderByTaskCreateTime()
.desc()
.list();
return tasks.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}
/**
* 获取组任务(候选任务)
*/
public List<TaskDTO> getCandidateTasks(String groupId) {
List<Task> tasks = taskService.createTaskQuery()
.taskCandidateGroup(groupId)
.orderByTaskCreateTime()
.desc()
.list();
return tasks.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}
/**
* 认领任务
*/
public void claimTask(String taskId, String userId) {
taskService.claim(taskId, userId);
}
/**
* 查询请假历史记录
*/
public List<LeaveRequestHistory> getLeaveHistory(String employeeId) {
List<HistoricProcessInstance> instances = historyService
.createHistoricProcessInstanceQuery()
.variableValueEquals("initiator", employeeId)
.orderByProcessInstanceStartTime()
.desc()
.list();
return instances.stream()
.map(this::convertToHistory)
.collect(Collectors.toList());
}
private TaskDTO convertToDTO(Task task) {
TaskDTO dto = new TaskDTO();
dto.setTaskId(task.getId());
dto.setTaskName(task.getName());
dto.setProcessInstanceId(task.getProcessInstanceId());
dto.setCreateTime(task.getCreateTime());
dto.setAssignee(task.getAssignee());
// 获取流程变量
Map<String, Object> variables = taskService.getVariables(task.getId());
dto.setVariables(variables);
return dto;
}
}
驳回处理委托
public class RejectDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
String processInstanceId = execution.getProcessInstanceId();
String initiator = (String) execution.getVariable("initiator");
String reason = (String) execution.getVariable("reason");
// 记录驳回原因
execution.setVariable("rejectReason", "请假申请被驳回");
// 这里可以发送通知、更新业务系统状态等
System.out.println("驳回请假申请: " + processInstanceId);
System.out.println("申请人: " + initiator);
System.out.println("请假原因: " + reason);
// 可以调用外部服务发送邮件、短信通知
// notificationService.sendRejectNotification(initiator);
}
}
通知委托
public class NotifyDelegate implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
String processInstanceId = execution.getProcessInstanceId();
String initiator = (String) execution.getVariable("initiator");
Boolean approved = (Boolean) execution.getVariable("approved");
if (Boolean.TRUE.equals(approved)) {
System.out.println("审批通过通知: " + processInstanceId);
// 发送通过通知
} else {
System.out.println("审批驳回通知: " + processInstanceId);
// 发送驳回通知
}
}
}
5.5 REST API
@RestController
@RequestMapping("/api/leave")
public class LeaveRequestController {
@Autowired
private LeaveRequestService leaveRequestService;
/**
* 提交请假申请
*/
@PostMapping("/submit")
public ResponseEntity<LeaveRequest> submitLeave(@RequestBody LeaveRequest request) {
LeaveRequest result = leaveRequestService.createLeaveRequest(request);
return ResponseEntity.ok(result);
}
/**
* 获取我的待办任务
*/
@GetMapping("/my-tasks")
public ResponseEntity<List<TaskDTO>> getMyTasks(@RequestParam String userId) {
List<TaskDTO> tasks = leaveRequestService.getMyTasks(userId);
return ResponseEntity.ok(tasks);
}
/**
* 获取候选任务
*/
@GetMapping("/candidate-tasks")
public ResponseEntity<List<TaskDTO>> getCandidateTasks(@RequestParam String groupId) {
List<TaskDTO> tasks = leaveRequestService.getCandidateTasks(groupId);
return ResponseEntity.ok(tasks);
}
/**
* 认领任务
*/
@PostMapping("/tasks/{taskId}/claim")
public ResponseEntity<Void> claimTask(
@PathVariable String taskId,
@RequestParam String userId) {
leaveRequestService.claimTask(taskId, userId);
return ResponseEntity.ok().build();
}
/**
* 完成审批
*/
@PostMapping("/tasks/{taskId}/complete")
public ResponseEntity<Void> completeTask(
@PathVariable String taskId,
@RequestBody ApprovalRequest approval) {
if ("managerApproval".equals(approval.getTaskName())) {
leaveRequestService.managerApproval(taskId, approval.isApproved(), approval.getComment());
} else if ("hrApproval".equals(approval.getTaskName())) {
leaveRequestService.hrApproval(taskId, approval.isApproved(), approval.getComment());
}
return ResponseEntity.ok().build();
}
/**
* 查询请假历史
*/
@GetMapping("/history")
public ResponseEntity<List<LeaveRequestHistory>> getHistory(@RequestParam String employeeId) {
List<LeaveRequestHistory> history = leaveRequestService.getLeaveHistory(employeeId);
return ResponseEntity.ok(history);
}
}
六、高级特性
6.1 并行网关
并行网关用于处理多个并发任务:
<parallelGateway id="fork"/>
<parallelGateway id="join"/>
<!-- 分支1 -->
<userTask id="task1" name="任务1"/>
<sequenceFlow sourceRef="fork" targetRef="task1"/>
<sequenceFlow sourceRef="task1" targetRef="join"/>
<!-- 分支2 -->
<userTask id="task2" name="任务2"/>
<sequenceFlow sourceRef="fork" targetRef="task2"/>
<sequenceFlow sourceRef="task2" targetRef="join"/>
<!-- 分支3 -->
<userTask id="task3" name="任务3"/>
<sequenceFlow sourceRef="fork" targetRef="task3"/>
<sequenceFlow sourceRef="task3" targetRef="join"/>
6.2 子流程
子流程用于封装可重用的流程片段:
<subProcess id="subProcess" name="审批子流程">
<startEvent id="subStart"/>
<userTask id="subTask" name="子流程任务"/>
<endEvent id="subEnd"/>
<sequenceFlow sourceRef="subStart" targetRef="subTask"/>
<sequenceFlow sourceRef="subTask" targetRef="subEnd"/>
</subProcess>
<callActivity id="callSubProcess" name="调用子流程"
calledElement="subProcess"/>
6.3 事件机制
Flowable支持多种事件类型:
- 定时器事件:基于时间的触发
- 消息事件:异步消息传递
- 信号事件:广播式通知
- 错误事件:异常处理
<!-- 定时器事件 -->
<intermediateCatchEvent id="timerEvent" name="等待通知">
<timerEventDefinition>
<timeDuration>PT2H</timeDuration>
</timerEventDefinition>
</intermediateCatchEvent>
<!-- 消息事件 -->
<intermediateCatchEvent id="messageEvent" name="接收消息">
<messageEventDefinition messageRef="approvalMessage"/>
</intermediateCatchEvent>
<!-- 边界定时器事件 -->
<boundaryEvent id="boundaryTimer" attachedToRef="userTask"
cancelActivity="true">
<timerEventDefinition>
<timeDuration>PT1H</timeDuration>
</timerEventDefinition>
</boundaryEvent>
6.4 监听器
通过监听器实现业务逻辑的扩展:
// 流程启动监听器
public class ProcessStartListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
String processDefinitionId = execution.getProcessDefinitionId();
System.out.println("流程启动: " + processDefinitionId);
// 记录日志、发送通知等
}
}
// 任务创建监听器
public class TaskCreateListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
String taskName = delegateTask.getName();
String assignee = delegateTask.getAssignee();
System.out.println("任务创建: " + taskName + ", 分配给: " + assignee);
// 发送任务通知
}
}
配置监听器:
<process id="leaveRequest">
<extensionElements>
<flowable:executionListener event="start"
class="com.example.flowable.listener.ProcessStartListener"/>
</extensionElements>
<userTask id="managerTask" flowable:assignee="${manager}">
<extensionElements>
<flowable:taskListener event="create"
class="com.example.flowable.listener.TaskCreateListener"/>
</extensionElements>
</userTask>
</process>
七、生产环境最佳实践
7.1 数据库优化
-- 为常用查询字段添加索引
CREATE INDEX idx_ru_task_ASSIGNEE ON ACT_RU_TASK(ASSIGNEE_);
CREATE INDEX idx_ru_task_PROC_INST ON ACT_RU_TASK(PROC_INST_ID_);
CREATE INDEX idx_hi_procinst_BUS_KEY ON ACT_HI_PROCINST(BUS_KEY_);
CREATE INDEX idx_hi_actinst_PROC_INST ON ACT_HI_ACTINST(PROC_INST_ID_);
-- 定期清理历史数据(根据业务需求配置保留时长)
DELETE FROM ACT_HI_VARINST WHERE END_TIME_ < DATE_SUB(NOW(), INTERVAL 1 YEAR);
DELETE FROM ACT_HI_DETAIL WHERE TIME_ < DATE_SUB(NOW(), INTERVAL 1 YEAR);
7.2 性能优化
- 异步执行:对耗时操作使用异步任务
<serviceTask id="asyncTask" name="异步任务"
flowable:async="true"
flowable:class="com.example.flowable.delegate.AsyncTaskDelegate"/>
- 批量操作:使用批量查询和操作API
// 批量查询任务
List<Task> tasks = taskService.createTaskQuery()
.taskAssignee("user1")
.listPage(0, 100);
// 批量完成任务
List<String> taskIds = Arrays.asList("task1", "task2", "task3");
taskService.completeBatchTasks(taskIds);
- 缓存配置:启用流程定义缓存
configuration.setProcessDefinitionCacheSize(100);
configuration.setEnableProcessDefinitionInfoCache(true);
7.3 安全配置
// 配置用户权限管理
IdentityService identityService = processEngine.getIdentityService();
// 创建用户
User user = identityService.newUser("zhangsan");
user.setFirstName("三");
user.setLastName("张");
user.setEmail("zhangsan@example.com");
identityService.saveUser(user);
// 创建组
Group group = identityService.newGroup("managers");
group.setName("经理组");
identityService.saveGroup(group);
// 分配用户到组
identityService.createMembership("zhangsan", "managers");
7.4 监控与告警
@Service
public class FlowableMonitorService {
@Autowired
private ManagementService managementService;
@Autowired
private RuntimeService runtimeService;
/**
* 获取运行中的流程统计
*/
public Map<String, Long> getProcessStatistics() {
Map<String, Long> stats = new HashMap<>();
// 各流程运行实例数
List<ProcessInstance> instances = runtimeService.createProcessInstanceQuery().list();
Map<String, Long> countByProcess = instances.stream()
.collect(Collectors.groupingBy(
ProcessInstance::getProcessDefinitionKey,
Collectors.counting()
));
stats.putAll(countByProcess);
// 待办任务统计
long pendingTasks = managementService.createTaskQuery().count();
stats.put("pendingTasks", pendingTasks);
return stats;
}
/**
* 检测异常流程(运行时间过长)
*/
public List<ProcessInstance> detectLongRunningProcesses(int thresholdHours) {
Date threshold = new Date(System.currentTimeMillis() - thresholdHours * 3600000L);
return runtimeService.createProcessInstanceQuery()
.startedBefore(threshold)
.list();
}
/**
* 获取数据库表信息
*/
public Map<String, Object> getDatabaseInfo() {
Map<String, Object> info = new HashMap<>();
// 获取各表记录数
String[] tables = {"ACT_RU_EXECUTION", "ACT_RU_TASK", "ACT_HI_PROCINST"};
for (String table : tables) {
long count = managementService.createTablePageQuery()
.tableName(table)
.listPage(0, 1)
.getTotal();
info.put(table, count);
}
return info;
}
}
八、微服务集成
在微服务架构中使用Flowable:
# application.yml配置
flowable:
# 数据库配置
datasource:
url: jdbc:mysql://localhost:3306/flowable?useSSL=false
username: flowable
password: flowable
driver-class-name: com.mysql.cj.jdbc.Driver
# 异步执行器配置
async-executor-activate: true
async-executor-max-jobs-per-acquisition: 10
async-executor-default-queue-size: 100
# REST API配置
rest:
enabled: true
# 邮件服务器配置
mail:
server:
host: smtp.example.com
port: 587
username: noreply@example.com
password: password
服务间通信示例:
@Service
public class WorkflowIntegrationService {
@Autowired
private RuntimeService runtimeService;
@Autowired
private RestTemplate restTemplate;
/**
* 跨服务启动流程
*/
public void startCrossServiceProcess(WorkflowRequest request) {
// 调用其他服务获取数据
UserDTO user = restTemplate.getForObject(
"http://user-service/api/users/" + request.getUserId(),
UserDTO.class
);
// 设置流程变量
Map<String, Object> variables = new HashMap<>();
variables.put("user", user);
variables.put("request", request);
// 启动流程
runtimeService.startProcessInstanceByKey(
"crossServiceProcess",
request.getBusinessKey(),
variables
);
}
/**
* 流程回调处理
*/
public void handleProcessCallback(String processInstanceId, String eventType) {
// 根据事件类型执行不同操作
switch (eventType) {
case "completed":
// 流程完成后的处理
handleProcessCompleted(processInstanceId);
break;
case "cancelled":
// 流程取消后的处理
handleProcessCancelled(processInstanceId);
break;
}
}
}
九、总结
Flowable作为一款优秀的开源工作流引擎,具有以下优势:
- 标准化:完全符合BPMN 2.0标准,学习成本低
- 轻量级:可嵌入任何Java应用,部署简单
- 高性能:支持高并发场景,适合企业级应用
- 灵活扩展:提供丰富的扩展点,易于定制
- 社区活跃:文档完善,社区支持良好