Flowable 是一个用 Java 编写的轻量级流程引擎,遵循 Apache 许可证 2.0。遵循 BPMN 2.0(业务流程建模与标注)标准,支持工作流、审批流、自动化任务等场景,能够满足不同复杂度的业务流程建模和执行需求。无论是简单的任务审批流程,还是复杂的业务规则驱动的流程,Flowable 都能有效应对。 特点:
- 支持嵌入式部署或独立服务部署。
- 提供 REST API 和 Java API 两种交互方式。
- 可扩展性强,支持自定义插件和事件监听。
- 与 Spring、Spring Boot 无缝集成。
与传统的 BPM 系统相比,Flowable 更加注重轻量化和可嵌入性。它可以轻松地集成到现有的 Java 应用程序中,无论是基于 Spring、Java EE 还是其他框架构建的应用,都能无缝衔接,无需额外的重量级基础设施支持。
二、核心功能模块
-
流程引擎
- Flowable 的流程引擎是其核心组件,负责管理业务流程的创建、执行和监控。它通过解析 BPMN 2.0 模型定义,将流程中的各个步骤、流转规则和参与者等信息转化为可执行的流程实例。
- 在执行过程中,引擎会根据预设的条件和规则,自动推进流程的流转,确保流程按照既定的路径顺利进行。同时,它还提供了丰富的 API,允许开发人员在流程执行过程中进行干预,如挂起、恢复、跳转等操作,以应对复杂的业务场景和异常情况。
-
任务管理
- 任务管理模块为流程中的任务分配、跟踪和处理提供了全面的支持。它能够根据流程定义和参与者的角色信息,将任务分配给相应的用户或系统参与者,并实时跟踪任务的执行状态。
- 开发人员可以通过 Flowable 提供的 REST API 或 Java API,方便地查询任务列表、获取任务详情、完成任务或转交任务等操作。此外,还可以设置任务的优先级、期限和提醒等属性,以确保任务能够及时、高效地完成。
-
数据存储与持久化
- Flowable 内置了对多种数据库的支持,能够将流程实例、任务信息、历史记录等数据持久化存储到数据库中。这不仅保证了数据的安全性和完整性,还为流程的监控和分析提供了数据基础。
- 它提供了灵活的数据库 schema,可以根据实际需求进行定制和扩展。同时,Flowable 还支持事务管理,确保在流程执行过程中数据的一致性和完整性。
-
历史与报表
- 历史模块记录了流程实例和任务的完整执行历史,包括每个步骤的执行时间、执行人员、执行结果等信息。这些历史数据对于流程的审计、优化和决策支持具有重要意义。
- 基于历史数据,Flowable 还提供了报表生成功能,能够生成各种类型的报表,如流程执行时间统计、任务完成情况统计等,帮助企业管理者更好地了解业务流程的运行状况,从而做出更明智的决策。
三、Flowable 的优势
-
高性能与可扩展性
- Flowable 采用了高效的并发处理机制和优化的数据库访问策略,能够在高并发的环境下稳定运行,满足企业大规模业务流程的处理需求。
- 它还支持集群部署,通过水平扩展的方式提高系统的吞吐量和可用性。在集群环境下,Flowable 可以自动进行负载均衡和故障转移,确保业务流程的连续性和稳定性。
-
灵活性与可定制性
- 如前文所述,Flowable 支持多种流程语言和建模方式,能够适应不同企业的业务流程特点和需求。同时,它提供了丰富的扩展点和插件机制,允许开发人员根据实际需求进行定制开发。
- 可以扩展流程引擎的行为、添加自定义的任务分配规则、集成第三方系统等功能,满足企业的个性化需求。这种灵活性使得 Flowable 能够在众多 BPM 解决方案中脱颖而出,成为企业的首选。
-
开源与社区支持
- 作为一款开源软件,Flowable 拥有活跃的社区和庞大的用户群体。社区成员积极贡献代码、分享经验和最佳实践,不断推动 Flowable 的发展和完善。
- 丰富的文档、示例代码和技术论坛等资源,为开发人员提供了全面的技术支持和学习机会,降低了企业使用 Flowable 的技术门槛和成本。
四、应用场景
-
企业级应用集成
- 在大型企业中,通常存在多个异构的系统,如 ERP、CRM、SCM 等。Flowable 可以作为企业级应用集成的中间件,将这些系统中的业务流程进行整合和自动化。
- 例如,当一个订单从 CRM 系统创建后,Flowable 可以根据预定义的流程,自动将订单信息传递给 ERP 系统进行库存分配和财务处理,同时通知 SCM 系统安排发货。通过这种方式,Flowable 实现了企业内部各系统之间的无缝协作,提高了业务流程的整体效率。
-
政务服务流程优化
- 政府部门的行政审批流程往往涉及多个环节和部门,流程复杂且耗时较长。Flowable 可以对政务服务流程进行建模和自动化,简化审批环节,提高审批效率。
- 例如,在工商注册审批流程中,通过 Flowable 可以将企业提交的注册申请自动分配给工商、税务、质监等部门进行并联审批,各部门在规定时间内完成审批任务后,Flowable 自动汇总审批结果并通知企业。这种流程优化不仅提高了政务服务的质量和效率,还为企业提供了更加便捷的服务体验。
-
金融行业风控流程管理
- 金融机构需要对各种业务流程进行严格的风险控制,如信贷审批、保险理赔等。Flowable 可以结合 DMN 模型,将业务规则和流程进行整合,实现在流程执行过程中自动应用风险控制规则。
- 例如,在信贷审批流程中,Flowable 可以根据借款人的信用评分、资产负债情况等信息,应用预先定义的 DMN 决策表,自动评估借款人的信用风险,并将审批结果反馈给信贷经理。通过这种方式,Flowable 帮助金融机构有效降低风险,提高决策的准确性和效率。
五、核心组件
Flowable 包含以下核心模块:
- Flowable Process Engine:处理 BPMN 2.0 流程定义与执行。
- Flowable Form Engine:管理动态表单定义。
- Flowable IDM Engine:用户、组和权限管理。
- Flowable Content Engine:存储流程相关附件。
- Flowable DMN Engine:决策表管理。
- Flowable CMMN Engine:案例管理模型支持。
六、Flowable 使用示例:
引入依赖
js
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.7.0</version>
<exclusions>
<exclusion>
<artifactId>mybatis</artifactId>
<groupId>org.mybatis</groupId>
</exclusion>
</exclusions>
</dependency>
OR:
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.7.0</version>
</dependency>
创建第一个流程: BPMN 请假申请
-
定义 BPMN 2.0 流程
创建一个 XML 文件(如 ``),定义简单审批流程:
xml``` <process id="leaveRequest" name="Leave Request Process"> <startEvent id="start"/> <userTask id="managerApproval" name="Manager Approval"/> <exclusiveGateway id="decision"/> <sequenceFlow sourceRef="start" targetRef="managerApproval"/> <sequenceFlow sourceRef="managerApproval" targetRef="decision"/> <!-- 更多节点定义 -->
```
-
开始事件(Start Event) : 标志着业务流程的开始。 开始事件 是 "员工发起请假申请" 这一动作,当员工在系统中提交请假申请表后,流程就开始了。
-
中间事件(Intermediate Event) : 在流程执行过程中,会对流程的走向产生影响。它可以是捕获事件(等待某件事发生,如等待消息到达、等待定时器到期)或抛出事件(触发某种动作,如发送消息)。
-
结束事件(End Event) : 表示业务流程的结束。当流程执行到结束事件时,流程实例就完成了。
-
任务(Task) : 流程中的具体工作项或操作。任务可以分配给人员、系统或组织来执行。根据执行主体的不同,有不同类型的任务。
- 用户任务(User Task) :需要人工参与的任务。"银行职员审核贷款申请材料"
- 服务任务(Service Task) :由系统自动执行的任务,通常用于调用后端服务或程序。"更新库存数量" 这个任务可以是一个服务任务
-
子流程(Sub - Process) :一个包含在另一个流程中的独立流程。它可以把一个复杂流程分解成多个较小的部分,便于理解和管理。子流程可以有自己的开始和结束事件、任务和网关等元素。
- 例如,在一个产品研发流程中,可以有一个名为 "需求分析子流程" 的子流程,这个子流程内部包含了收集用户需求、分析需求可行性等一系列任务和决策节点。
-
排他网关(Exclusive Gateway) :用于在流程中进行条件判断,根据不同的条件将流程引导到不同的分支。当流程执行到排他网关时,只会选择一个满足条件的分支继续执行。金额大于等于 1000 元,进入 "总经理审批" 分支。
-
并行网关(Parallel Gateway) :使流程同时沿着多个分支并行执行。所有分支会同时开始执行,并且在流程汇聚时,需要等到所有并行分支都执行完毕后才会继续后续的流程。
-
包含网关(Inclusive Gateway) :允许一个流程沿着多个分支同时执行,并且在后续汇聚时,只要满足条件的分支执行完毕后就可以继续。与排他网关不同,它可以在多个分支满足条件的情况下同时执行多个分支。 设置包含网关来判断是否同时在社交媒体和线下渠道进行推广。 都符合条件,那么两个渠道的推广活动分支会同时执行。
leave-request.bpmn20.xml
js
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
<process id="leaveRequestProcess" name="请假申请流程" isExecutable="true">
<!-- 开始事件 -->
<startEvent id="startEvent">
<outgoing>flow1</outgoing>
</startEvent>
<!-- 用户任务:提交请假申请 -->
<userTask id="submitLeaveTask" name="提交请假申请" flowable:assignee="${initiator}">
<extensionElements>
<flowable:formProperty id="leaveType" name="请假类型" type="enum" required="true">
<flowable:value id="annualLeave" name="年假"/>
<flowable:value id="sickLeave" name="病假"/>
<flowable:value id="personalLeave" name="事假"/>
</flowable:formProperty>
<flowable:formProperty id="startDate" name="开始日期" type="date" required="true"/>
<flowable:formProperty id="endDate" name="结束日期" type="date" required="true"/>
<flowable:formProperty id="reason" name="请假原因" type="string" required="true"/>
</extensionElements>
<incoming>flow1</incoming>
<outgoing>flow2</outgoing>
</userTask>
<!-- 网关:判断是否撤销申请 -->
<exclusiveGateway id="withdrawGateway" name="判断是否撤销申请">
<incoming>flow2</incoming>
<outgoing>flow2a</outgoing>
<outgoing>flow2b</outgoing>
</exclusiveGateway>
<!-- 用户任务:撤销申请 -->
<userTask id="withdrawTask" name="撤销申请" flowable:assignee="${initiator}">
<extensionElements>
<flowable:formProperty id="withdrawReason" name="撤销原因" type="string" required="true"/>
</extensionElements>
<incoming>flow2a</incoming>
<outgoing>flow8</outgoing>
</userTask>
<!-- 序列流:发起人选择撤销 -->
<sequenceFlow id="flow2a" sourceRef="withdrawGateway" targetRef="withdrawTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${withdraw == true}]]></conditionExpression>
</sequenceFlow>
<!-- 序列流:发起人不选择撤销 -->
<sequenceFlow id="flow2b" sourceRef="withdrawGateway" targetRef="approverGateway">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${withdraw == false}]]></conditionExpression>
</sequenceFlow>
<!-- 结束事件:撤销申请结束 -->
<endEvent id="withdrawEndEvent" name="撤销申请结束">
<incoming>flow8</incoming>
</endEvent
<!-- 序列流:撤销申请到结束 -->
<sequenceFlow id="flow8" sourceRef="withdrawTask" targetRef="withdrawEndEvent"/>
<!-- 网关:判断审批人 -->
<exclusiveGateway id="approverGateway" name="判断审批人">
<incoming>flow2b</incoming>
<outgoing>flow3</outgoing>
<outgoing>flow4</outgoing>
</exclusiveGateway>
<!-- 序列流:根据请假天数判断审批人 -->
<sequenceFlow id="flow3" sourceRef="approverGateway" targetRef="managerApproveTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${durationInDays <= 3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" sourceRef="approverGateway" targetRef="hrApproveTask">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${durationInDays > 3}]]></conditionExpression>
</sequenceFlow>
<!-- 用户任务:经理审批 -->
<userTask id="managerApproveTask" name="经理审批" flowable:candidateGroups="managers">
<extensionElements>
<flowable:formProperty id="approval" name="是否批准" type="boolean" required="true"/>
</extensionElements>
<incoming>flow3</incoming>
<outgoing>flow5</outgoing>
</userTask>
<!-- 用户任务:HR 审批 -->
<userTask id="hrApproveTask" name="HR 审批" flowable:candidateGroups="hr">
<extensionElements>
<flowable:formProperty id="approval" name="是否批准" type="boolean" required="true"/>
</extensionElements>
<incoming>flow4</incoming>
<outgoing>flow5</outgoing>
</userTask>
<!-- 网关:判断审批结果 -->
<exclusiveGateway id="resultGateway" name="判断审批结果">
<incoming>flow5</incoming>
<outgoing>flow6</outgoing>
<outgoing>flow7</outgoing>
</exclusiveGateway>
<!-- 序列流:根据审批结果分流 -->
<sequenceFlow id="flow6" sourceRef="resultGateway" targetRef="approveEndEvent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${approval == true}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow7" sourceRef="resultGateway" targetRef="rejectEndEvent">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${approval == false}]]></conditionExpression>
</sequenceFlow>
<!-- 结束事件:审批通过 -->
<endEvent id="approveEndEvent" name="审批通过">
<incoming>flow6</incoming>
</endEvent>
<!-- 结束事件:审批拒绝 -->
<endEvent id="rejectEndEvent" name="审批拒绝">
<incoming>flow7</incoming>
</endEvent>
<!-- 序列流定义 -->
<sequenceFlow id="flow1" sourceRef="startEvent" targetRef="submitLeaveTask"/>
</process>
</definitions>
-
部署流程
使用
RepositoryService
部署流程定义:scss@Autowired private RepositoryService repositoryService; public void deployProcess() { repositoryService.createDeployment() .addClasspathResource("processes/leave-request.bpmn20.xml") .deploy(); }
-
启动流程实例
typescript@Autowired private RuntimeService runtimeService; public void startProcess() { Map<String, Object> variables = new HashMap<>(); variables.put("employee", "John Doe"); runtimeService.startProcessInstanceByKey("leaveRequest", variables); }
-
其他接口
scss
2.提供一大波模型与流程定义的通用方法
模型相关
repositoryService.getModel() (获取模型)
repositoryService.saveModel() (保存模型)
repositoryService.deleteModel() (删除模型)
repositoryService.createDeployment().deploy(); (部署模型)
repositoryService.getModelEditorSource() (获得模型JSON数据的UTF8字符串)
repositoryService.getModelEditorSourceExtra() (获取PNG格式图像)
3.流程定义相关
repositoryService.getProcessDefinition(ProcessDefinitionId); 获取流程定义具体信息
repositoryService.activateProcessDefinitionById() 激活流程定义
repositoryService.suspendProcessDefinitionById() 挂起流程定义
repositoryService.deleteDeployment() 删除流程定义
repositoryService.getProcessDiagram()获取流程定义图片流
repositoryService.getResourceAsStream()获取流程定义xml流
repositoryService.getBpmnModel(pde.getId()) 获取bpmn对象(当前进行到的那个节点的流程图使用)
4.流程定义授权相关
repositoryService.getIdentityLinksForProcessDefinition() 流程定义授权列表
repositoryService.addCandidateStarterGroup()新增组流程授权
repositoryService.addCandidateStarterUser()新增用户流程授权
repositoryService.deleteCandidateStarterGroup() 删除组流程授权
repositoryService.deleteCandidateStarterUser() 删除用户流程授权
runtimeService.createProcessInstanceBuilder().start() 发起流程
runtimeService.deleteProcessInstance() 删除正在运行的流程
runtimeService.suspendProcessInstanceById() 挂起流程定义
runtimeService.activateProcessInstanceById() 激活流程实例
runtimeService.getVariables(processInstanceId); 获取表单中填写的值
runtimeService.getActiveActivityIds(processInstanceId)获取以进行的流程图节点 (当前进行到的那个节点的流程图使用)
runtimeService.createChangeActivityStateBuilder().moveExecutionsToSingleActivityId(executionIds, endId).changeState(); 终止流程
historyService.createHistoricProcessInstanceQuery().list() 查询流程实例列表(历史流程,包括未完成的)
historyService.createHistoricProcessInstanceQuery().list().foreach().getValue() 可以获取历史中表单的信息
historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); 根绝id查询流程实例
historyService.deleteHistoricProcessInstance() 删除历史流程
historyService.deleteHistoricTaskInstance(taskid); 删除任务实例
historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list() 流程实例节点列表 (当前进行到的那个节点的流程图使用)
流转的节点审批
taskService.createTaskQuery().list() 待办任务列表
taskService.createTaskQuery().taskId(taskId).singleResult(); 待办任务详情
taskService.saveTask(task); 修改任务
taskService.setAssignee() 设置审批人
taskService.addComment() 设置审批备注
taskService.complete() 完成当前审批
taskService.getProcessInstanceComments(processInstanceId); 查看任务详情(也就是都经过哪些人的审批,意见是什么)
taskService.delegateTask(taskId, delegater); 委派任务
taskService.claim(taskId, userId);认领任务
taskService.unclaim(taskId); 取消认领
taskService.complete(taskId, completeVariables); 完成任务
任务授权
taskService.addGroupIdentityLink()新增组任务授权
taskService.addUserIdentityLink() 新增人员任务授权
taskService.deleteGroupIdentityLink() 删除组任务授权
taskService.deleteUserIdentityLink() 删除人员任务授权
identityService.createUserQuery().userId(userId).singleResult(); 获取审批用户的具体信息
identityService.createGroupQuery().groupId(groupId).singleResult(); 获取审批组的具体信息
自定义 BpmnModel
scss
import org.activiti.bpmn.model.*;
import org.activiti.bpmn.converter.BpmnXMLConverter;
public class CustomProcessDesignerExample {
public static void main(String[] args) {
// 创建一个 BpmnModel 实例
BpmnModel bpmnModel = new BpmnModel();
// 创建一个流程实例
Process process = new Process();
process.setId("customProcess"); // 设置流程 ID
process.setName("Custom Process"); // 设置流程名称
// 创建一个开始节点
StartEvent startEvent = new StartEvent();
startEvent.setId("startEvent");
process.addFlowElement(startEvent); // 将开始节点添加到流程中
// 创建一个用户任务节点
UserTask userTask = new UserTask();
userTask.setId("userTask");
userTask.setName("Custom User Task");
process.addFlowElement(userTask); // 将用户任务节点添加到流程中
// 创建一个结束节点
EndEvent endEvent = new EndEvent();
endEvent.setId("endEvent");
process.addFlowElement(endEvent); // 将结束节点添加到流程中
// 创建节点之间的连接关系
SequenceFlow startToUserTask = new SequenceFlow();
startToUserTask.setId("flow1");
startToUserTask.setSourceRef(startEvent.getId());
startToUserTask.setTargetRef(userTask.getId());
process.addFlowElement(startToUserTask);
SequenceFlow userTaskToEnd = new SequenceFlow();
userTaskToEnd.setId("flow2");
userTaskToEnd.setSourceRef(userTask.getId());
userTaskToEnd.setTargetRef(endEvent.getId());
process.addFlowElement(userTaskToEnd);
// 将流程添加到 BpmnModel 中
bpmnModel.addProcess(process);
// 创建 BpmnXMLConverter 实例
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
// 将 BpmnModel 转换为 XML 字节数据
byte[] convertToXML = bpmnXMLConverter.convertToXML(bpmnModel);
// 打印 XML 内容(这里只是简单展示,实际项目中可以将 XML 写入文件等操作)
System.out.println(new String(convertToXML));
}
}
高级特性
事件监听器
实现 FlowableEventListener
监听任务创建事件:
csharp
public class TaskCreatedListener implements FlowableEventListener {
@Override
public void onEvent(FlowableEvent event) {
Task task = (Task) event.getEntity();
System.out.println("Task created: " + task.getName());
}
}
服务任务与委托表达式
在 BPMN 中调用 Java 逻辑:
bash
<serviceTask id="sendEmail" flowable:delegateExpression="${emailServiceDelegate}"/>
表结构
Flowable 数据库表命名规则
ACT_RE_ * : 'RE'表示 repository(存储)。RepositoryService 接口操作的表。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。
ACT_RU_ * : 'RU'表示 runtime。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。flowable 只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。
ACT_ID_ * : 'ID'表示 identity (组织机构)。这些表包含标识的信息,如用户,用户组,等等。
ACT_HI_ * : 'HI'表示 history。就是这些表包含着历史的相关数据,如结束的流程实例,变量,任务,等等。
ACT_GE_ * : 普通数据,各种情况都使用的数据。
数据库表结构 (30+)
一般数据 (2)
ACT_GE_BYTEARRAY 通用的流程定义和流程资源
ACT_GE_PROPERTY 系统相关属性
流程历史记录 (8)
ACT_HI_ACTINST 历史的流程实例
ACT_HI_ATTACHMENT 历史的流程附件
ACT_HI_COMMENT 历史的说明性信息
ACT_HI_DETAIL 历史的流程运行中的细节信息
ACT_HI_IDENTITYLINK 历史的流程运行过程中用户关系
ACT_HI_PROCINST 历史的流程实例
ACT_HI_TASKINST 历史的任务实例
ACT_HI_VARINST 历史的流程运行中的变量信息
用户用户组表 (9)
ACT_ID_BYTEARRAY 二进制数据表
ACT_ID_GROUP 用户组信息表
ACT_ID_INFO 用户信息详情表
ACT_ID_MEMBERSHIP 人与组关系表
ACT_ID_PRIV 权限表
ACT_ID_PRIV_MAPPING 用户或组权限关系表
ACT_ID_PROPERTY 属性表
ACT_ID_TOKEN 系统登录日志表
ACT_ID_USER 用户表
流程定义表 (3)
ACT_RE_DEPLOYMENT 部署单元信息
ACT_RE_MODEL 模型信息
ACT_RE_PROCDEF 已部署的流程定义
运行实例表 (10)
ACT_RU_DEADLETTER_JOB 正在运行的任务表
ACT_RU_EVENT_SUBSCR 运行时事件
ACT_RU_EXECUTION 运行时流程执行实例
ACT_RU_HISTORY_JOB 历史作业表
ACT_RU_IDENTITYLINK 运行时用户关系信息
ACT_RU_JOB 运行时作业表
ACT_RU_SUSPENDED_JOB 暂停作业表
ACT_RU_TASK 运行时任务表
ACT_RU_TIMER_JOB 定时作业表
ACT_RU_VARIABLE 运行时变量表
其他表 (2)
ACT_EVT_LOG 事件日志表
ACT_PROCDEF_INFO 流程定义信息