工作中最常用的5种工作流引擎

企业应用数据库开发与运维

大家好,我是苏三,又跟大家见面了。

前言

有些小伙伴在工作中,一提到工作流引擎就头疼,不知道如何选型,更不清楚它们底层的原理。

其实,工作流引擎就像我们生活中的交通信号系统,它负责协调各个"路口"(业务节点)的通行顺序,确保整个"交通"(业务流程)有序进行。

今天我想和大家聊聊工作中最常用的5种工作流引擎,希望对你会有所帮助。

最近建了一些工作内推群,各大城市都有,欢迎各位HR和找工作的小伙伴进群交流,群里目前已经收集了不少的工作内推岗位。

扫码加苏三的微信:li_su223,备注:所在城市,即可进群。

picture.image

一、工作流引擎是什么?

在深入具体引擎之前,我们先明确一个基本概念:工作流引擎本质上是业务流程自动化的核心支撑系统

它负责将复杂的业务逻辑分解为多个任务节点,并控制这些节点之间的流转逻辑。

举个例子,比如一个请假审批流程:员工提交申请 → 直接主管审批 → 部门经理审批 → HR备案 → 结束。

如果每个环节都用if-else硬编码,代码会变得极其臃肿且难以维护。

而工作流引擎通过可视化的方式定义流程,让业务逻辑和流程控制彻底解耦。

为了让大家更直观地理解工作流引擎的架构,我画了一个整体架构图:

picture.image

这张图展示了工作流引擎的核心组件。接下来,我们看看为什么要用工作流引擎:

  1. 降低复杂度 :将业务流程从业务代码中解耦
  2. 提高可维护性 :流程变更只需修改配置,无需改代码
  3. 增强可视化 :大多数引擎提供流程设计器和监控界面
  4. 保证一致性 :通过状态机保证业务流程的标准执行

有些小伙伴在工作中可能会问:"我们系统业务逻辑不复杂,需要用工作流引擎吗?"

我的经验是:当你的业务有状态流转、多人协作、需要长时间运行的特征时,就应该考虑使用工作流引擎了。

二、Activiti:企业级标准工作流引擎

Activiti可以说是Java领域最老牌、最知名的工作流引擎之一,它最初是jBPM的原作者离开JBoss后创建的。

核心原理

Activiti基于BPMN 2.0标准 ,采用状态机+命令模式 的设计。

它的核心思想是将业务流程抽象为一系列的活动节点,通过令牌(Token)在节点间的流动来驱动流程执行。

架构特点

  • 支持完整的BPMN 2.0元素
  • 采用命令模式,所有操作都封装为命令
  • 基于状态机管理流程实例状态
  • 支持事务性流程执行

开源地址

GitHub: https://github.com/Activiti/Activiti

示例:请假审批流程

首先在Spring Boot项目中引入依赖:

  
<dependency>  
    <groupId>org.activiti</groupId>  
    <artifactId>activiti-spring-boot-starter</artifactId>  
    <version>7.1.0.M6</version>  
</dependency>  

定义BPMN 2.0流程文件(leave-approval.bpmn20.xml):

  
<?xml version="1.0" encoding="UTF-8"?>  
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">  
    <process id="leaveApproval" name="请假审批流程" isExecutable="true">  
        <!-- 开始事件 -->  
        <startEvent id="startEvent" />  
          
        <!-- 用户提交申请 -->  
        <userTask id="submitLeave" name="提交请假申请"   
                 activiti:assignee="#{employee}"/>  
          
        <!-- 主管审批 -->  
        <userTask id="leaderApproval" name="直接主管审批"  
                 activiti:assignee="#{leader}"/>  
          
        <!-- 排他网关:根据审批结果决定流向 -->  
        <exclusiveGateway id="decisionGateway"/>  
          
        <!-- 条件序列流:审批通过 -->  
        <sequenceFlow id="flowApproved" sourceRef="decisionGateway" targetRef="hrRecord">  
            <conditionExpression xsi:type="tFormalExpression">  
                <![CDATA[${approved == true}]]>  
            </conditionExpression>  
        </sequenceFlow>  
          
        <!-- 条件序列流:审批驳回 -->  
        <sequenceFlow id="flowRejected" sourceRef="decisionGateway" targetRef="rejectEnd">  
            <conditionExpression xsi:type="tFormalExpression">  
                <![CDATA[${approved == false}]]>  
            </conditionExpression>  
        </sequenceFlow>  
          
        <!-- HR备案 -->  
        <userTask id="hrRecord" name="HR备案"   
                 activiti:assignee="#{hr}"/>  
          
        <!-- 结束事件 -->  
        <endEvent id="endEvent" />  
    </process>  
</definitions>  

Java代码中启动和执行流程:

  
@Service  
@Transactional  
publicclass LeaveProcessService {  
      
    @Autowired  
    private RuntimeService runtimeService;  
      
    @Autowired  
    private TaskService taskService;  
      
    @Autowired  
    private RepositoryService repositoryService;  
      
    // 部署流程定义  
    public void deployProcess() {  
        repositoryService.createDeployment()  
            .addClasspathResource("processes/leave-approval.bpmn20.xml")  
            .name("请假审批流程")  
            .deploy();  
    }  
      
    // 启动请假流程  
    public void startLeaveProcess(String employee, String leader, int leaveDays) {  
        Map<String, Object> variables = new HashMap<>();  
        variables.put("employee", employee);  
        variables.put("leader", leader);  
        variables.put("hr", "hr\_department");  
        variables.put("leaveDays", leaveDays);  
        // 启动时尚未有审批结果,approved变量稍后设置  
        variables.put("approved", null);  
          
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(  
            "leaveApproval", variables);  
          
        System.out.println("流程启动成功,实例ID:" + processInstance.getId());  
    }  
      
    // 查询用户待办任务  
    public List<Task> getPendingTasks(String assignee) {  
        return taskService.createTaskQuery()  
            .taskAssignee(assignee)  
            .orderByTaskCreateTime().desc()  
            .list();  
    }  
      
    // 完成任务并传递审批结果  
    public void completeTask(String taskId, boolean approved, String comment) {  
        Map<String, Object> variables = new HashMap<>();  
        variables.put("approved", approved);  
          
        // 添加审批意见  
        if (comment != null && !comment.trim().isEmpty()) {  
            taskService.addComment(taskId, null, comment);  
        }  
          
        taskService.complete(taskId, variables);  
        System.out.println("任务完成,审批结果:" + (approved ? "通过" : "驳回"));  
    }  
}  

代码逻辑深度解析

  1. 流程定义 :BPMN文件定义了节点拓扑结构, userTask 表示人工任务, exclusiveGateway 是决策点
  2. 变量传递 :通过 variables 映射表在流程实例中传递业务数据
  3. 任务查询 :Activiti自动维护任务状态,通过 TaskQuery API查询待办
  4. 状态持久化 :所有流程状态自动持久化到数据库,保证一致性

有些小伙伴在工作中可能会遇到Activiti表太多的问题,其实这是因为它采用分表设计ACT\_RE\_*存储静态定义,ACT\_RU\_*存储运行时数据,ACT\_HI\_*存储历史数据。

这种设计既保证了运行时性能,又支持历史追溯。

三、Flowable:Activiti的性能优化版

Flowable是Activiti的原班人马创建的分支项目,在性能和云原生支持方面有显著改进。

它完全兼容Activiti的API,但内部进行了大量优化。

核心原理

Flowable在Activiti的基础上引入了异步执行器执行树优化

它通过更精细的锁管理和批量处理来提升高并发下的性能。

架构改进

  • 增强的异步执行器,支持批量操作
  • 优化的执行树结构,减少数据库访问
  • 更好的缓存管理和懒加载策略
  • 原生支持Spring Boot Starter

开源地址

GitHub: https://github.com/flowable/flowable-engine

示例:订单处理流程(含服务任务)

Flowable特别擅长处理自动化业务流程,下面是一个订单处理示例:

  
@Service  
publicclass OrderProcessService {  
      
    @Autowired  
    private RuntimeService runtimeService;  
      
    @Autowired  
    private RepositoryService repositoryService;  
      
    // 部署订单流程  
    public void deployOrderProcess() {  
        repositoryService.createDeployment()  
            .addClasspathResource("processes/order-process.bpmn20.xml")  
            .addClasspathResource("processes/order-discount.dmn") // DMN决策表  
            .deploy();  
    }  
      
    // 启动订单流程  
    public void startOrderProcess(Order order) {  
        Map<String, Object> variables = new HashMap<>();  
        variables.put("order", order);  
        variables.put("customerService", "cs\_team");  
        variables.put("warehouse", "wh\_team");  
          
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(  
            "orderProcess", order.getOrderNo(), variables);  
          
        logger.info("订单流程启动: {}", processInstance.getId());  
    }  
}  
  
// 服务任务处理器 - 库存检查  
@Component  
publicclass InventoryCheckDelegate implements JavaDelegate {  
      
    @Autowired  
    private InventoryService inventoryService;  
      
    @Override  
    public void execute(DelegateExecution execution) {  
        Order order = (Order) execution.getVariable("order");  
          
        // 调用库存服务检查库存  
        boolean inStock = inventoryService.checkInventory(  
            order.getProductId(), order.getQuantity());  
          
        execution.setVariable("inStock", inStock);  
          
        if (!inStock) {  
            execution.setVariable("needBackorder", true);  
            logger.warn("产品{}库存不足,需要备货", order.getProductId());  
        }  
    }  
}  
  
// 服务任务处理器 - 支付处理  
@Component  
publicclass PaymentProcessDelegate implements JavaDelegate {  
      
    @Autowired  
    private PaymentService paymentService;  
      
    @Override  
    public void execute(DelegateExecution execution) {  
        Order order = (Order) execution.getVariable("order");  
          
        try {  
            // 调用支付网关  
            PaymentResult result = paymentService.processPayment(order);  
            execution.setVariable("paymentSuccess", result.isSuccess());  
            execution.setVariable("paymentId", result.getPaymentId());  
              
        } catch (Exception e) {  
            execution.setVariable("paymentSuccess", false);  
            execution.setVariable("paymentError", e.getMessage());  
            thrownew RuntimeException("支付处理失败", e);  
        }  
    }  
}  

对应的BPMN流程包含服务任务:

  
<process id="orderProcess" name="订单处理流程">  
    <startEvent id="start" />  
      
    <!-- 库存检查服务任务 -->  
    <serviceTask id="inventoryCheck" name="库存检查"  
                 activiti:class="com.example.InventoryCheckDelegate"/>  
      
    <!-- 库存决策网关 -->  
    <exclusiveGateway id="inventoryDecision" />  
      
    <!-- 有库存流程 -->  
    <sequenceFlow id="inStockFlow" sourceRef="inventoryDecision" targetRef="paymentProcess">  
        <conditionExpression>${inStock == true}</conditionExpression>  
    </sequenceFlow>  
      
    <!-- 无库存流程 -->  
    <sequenceFlow id="outOfStockFlow" sourceRef="inventoryDecision" targetRef="backorderTask">  
        <conditionExpression>${inStock == false}</conditionExpression>  
    </sequenceFlow>  
      
    <!-- 支付处理 -->  
    <serviceTask id="paymentProcess" name="支付处理"  
                 activiti:class="com.example.PaymentProcessDelegate"/>  
      
    <!-- 备货任务 -->  
    <userTask id="backorderTask" name="备货处理"   
              activiti:assignee="#{warehouse}"/>  
      
    <endEvent id="end" />  
</process>  

深度原理剖析

  1. 服务任务异步执行 :Flowable的 JavaDelegate 默认支持异步执行,避免阻塞主线程
  2. 执行树优化 :Flowable将流程执行建模为执行树,减少状态同步开销
  3. 批量事件处理 :多个流程实例的事件可以批量处理,提升吞吐量
  4. DMN集成 :内置DMN决策引擎,支持复杂业务规则

有些小伙伴在工作中处理高并发场景时,Flowable的异步执行器 特别有用。

它能够将耗时的服务任务放入消息队列异步处理,避免数据库长事务。

四、Camunda:微服务架构的首选

Camunda是另一个流行的Activiti分支,特别强调运维监控微服务集成 能力。

它提供了完整的操作工具链。

核心原理

Camunda采用外部任务模式乐观锁并发控制 。它的核心思想是将工作流引擎与业务服务解耦,通过外部任务队列实现松耦合集成。

架构特色

  • 外部任务模式,支持多语言客户端
  • 完整的监控工具Cockpit和Tasklist
  • 基于乐观锁的高并发控制
  • 原生支持微服务架构模式

开源地址

GitHub: https://github.com/camunda/camunda-bpm-platform

示例:贷款审批流程(外部任务模式)

Camunda的外部任务模式特别适合微服务架构:

  
// 贷款申请DTO  
@Data  
publicclass LoanApplication {  
    private String applicationId;  
    private String applicantName;  
    privatedouble amount;  
    privateint duration;  
    privatedouble income;  
    privateint creditScore;  
}  
  
// 贷款流程启动服务  
@Service  
@Transactional  
publicclass LoanProcessService {  
      
    @Autowired  
    private RuntimeService runtimeService;  
      
    public void startLoanProcess(LoanApplication application) {  
        Map<String, Object> variables = new HashMap<>();  
        variables.put("application", application);  
        variables.put("creditCheckRequired", application.getAmount() > 100000);  
        variables.put("autoApprovalLimit", 50000.0);  
          
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(  
            "loanApprovalProcess", application.getApplicationId(), variables);  
          
        logger.info("贷款流程启动: {}", processInstance.getId());  
    }  
}  
  
// 征信检查外部任务工作者  
@Component  
publicclass CreditCheckWorker {  
      
    @Autowired  
    private ExternalTaskService externalTaskService;  
      
    @Autowired  
    private CreditService creditService;  
      
    @PostConstruct  
    public void startCreditCheckWorker() {  
        new Thread(() -> {  
            while (true) {  
                try {  
                    // 获取外部任务  
                    List<LockedExternalTask> tasks = externalTaskService  
                        .fetchAndLock(10, "credit-check-worker")  
                        .topic("credit-check", 60000L)  
                        .execute();  
                      
                    for (LockedExternalTask task : tasks) {  
                        processCreditCheck(task);  
                    }  
                      
                    Thread.sleep(5000); // 5秒轮询  
                      
                } catch (Exception e) {  
                    logger.error("征信检查工作者异常", e);  
                }  
            }  
        }).start();  
    }  
      
    private void processCreditCheck(LockedExternalTask task) {  
        try {  
            LoanApplication application = (LoanApplication)   
                task.getVariable("application");  
              
            // 调用外部征信系统  
            CreditReport report = creditService.getCreditReport(  
                application.getApplicantName(), application.getApplicantId());  
              
            Map<String, Object> variables = new HashMap<>();  
            variables.put("creditReport", report);  
            variables.put("creditScore", report.getScore());  
            variables.put("creditCheckPassed", report.getScore() > 600);  
              
            // 完成任务  
            externalTaskService.complete(task.getId(), "credit-check-worker", variables);  
              
            logger.info("征信检查完成: {}", application.getApplicationId());  
              
        } catch (Exception e) {  
            // 处理失败,解锁任务以便重试  
            externalTaskService.handleFailure(task.getId(), "credit-check-worker",   
                e.getMessage(), 3, 30000L);  
        }  
    }  
}  
  
// 风险评估外部任务工作者  
@Component  
publicclass RiskAssessmentWorker {  
      
    @Autowired  
    private RiskService riskService;  
      
    public void startRiskAssessmentWorker() {  
        // 类似的实现模式  
        // 订阅"risk-assessment"主题  
    }  
}  

Camunda还提供强大的运维监控 能力:

  
// 流程实例监控  
@Service  
publicclass ProcessMonitorService {  
      
    @Autowired  
    private HistoryService historyService;  
      
    @Autowired  
    private ManagementService managementService;  
      
    // 获取流程实例统计  
    public Map<String, Object> getProcessStats(String processDefinitionKey) {  
        Map<String, Object> stats = new HashMap<>();  
          
        // 运行中实例数量  
        long runningInstances = historyService.createHistoricProcessInstanceQuery()  
            .processDefinitionKey(processDefinitionKey)  
            .unfinished()  
            .count();  
          
        // 今日完成数量  
        long todayCompleted = historyService.createHistoricProcessInstanceQuery()  
            .processDefinitionKey(processDefinitionKey)  
            .finishedAfter(TemporalUtil.todayStart())  
            .count();  
          
        // 平均处理时间  
        HistoricProcessInstanceQuery query = historyService  
            .createHistoricProcessInstanceQuery()  
            .processDefinitionKey(processDefinitionKey)  
            .finished();  
          
        stats.put("runningInstances", runningInstances);  
        stats.put("todayCompleted", todayCompleted);  
        stats.put("avgDuration", calculateAverageDuration(query));  
          
        return stats;  
    }  
}  

架构深度解析

  1. 外部任务模式 :业务逻辑在引擎外部执行,支持多语言和技术栈
  2. 主题订阅机制 :工作者订阅特定主题的任务,实现关注点分离
  3. 乐观锁控制 :通过版本号避免并发冲突,提高吞吐量
  4. 完整的运维体系 :Cockpit提供实时监控,Optimize提供流程分析

Camunda的这种设计特别适合微服务架构 ,每个微服务可以独立开发部署,通过外部任务与工作流引擎交互。

五、jBPM:规则集成的最佳选择

jBPM是红帽旗下的开源BPM套件,基于KIE(Knowledge Is Everything)平台,与Drools规则引擎深度集成。

核心原理

jBPM采用知识会话 模式,将流程引擎和规则引擎统一在同一个会话中。

这种设计使得业务流程和业务规则能够无缝协作。

架构特色

  • 与Drools规则引擎深度集成
  • 基于知识会话的统一执行环境
  • 支持BPMN 2.0和CMN(案例管理)
  • 完整的生命周期管理

开源地址

GitHub: https://github.com/kiegroup/jbpm

示例:保险理赔流程(规则集成)

jBPM最大的优势在于规则和流程的集成:

  
// 保险理赔DTO  
@Data  
publicclass InsuranceClaim {  
    private String claimId;  
    private String policyNumber;  
    private String claimType; // AUTO, HEALTH, PROPERTY  
    privatedouble claimAmount;  
    private Date incidentDate;  
    private String description;  
    privateboolean fraudulent = false;  
    privatedouble approvedAmount = 0.0;  
}  
  
// 理赔流程服务  
@Service  
publicclass ClaimProcessService {  
      
    @Autowired  
    private RuntimeEngine runtimeEngine;  
      
    @Autowired  
    private KieContainer kieContainer;  
      
    public void startClaimProcess(InsuranceClaim claim) {  
        // 创建KIE会话  
        KieSession kieSession = kieContainer.newKieSession();  
          
        try {  
            // 插入事实对象到规则引擎  
            kieSession.insert(claim);  
            kieSession.insert(new Date());  
              
            // 启动流程实例  
            ProcessInstance processInstance = runtimeEngine.getKieSession()  
                .startProcess("claimApprovalProcess",   
                    createProcessVariables(claim));  
              
            logger.info("理赔流程启动: {}", processInstance.getId());  
              
        } finally {  
            kieSession.dispose();  
        }  
    }  
      
    private Map<String, Object> createProcessVariables(InsuranceClaim claim) {  
        Map<String, Object> variables = new HashMap<>();  
        variables.put("claim", claim);  
        variables.put("claimAmount", claim.getClaimAmount());  
        variables.put("claimType", claim.getClaimType());  
        variables.put("autoApprovalLimit", 5000.0);  
        variables.put("requiresManagerApproval", claim.getClaimAmount() > 10000);  
        return variables;  
    }  
}  
  
// 欺诈检测规则(DRL文件)  
rule "High Amount Fraud Detection"  
    when  
        $claim : InsuranceClaim(claimAmount > 50000)  
        Date() // 当前日期  
    then  
        $claim.setFraudulent(true);  
        modify($claim);  
        System.out.println("检测到大额理赔,标记为可疑欺诈: " + $claim.getClaimId());  
end  
  
rule "Quick Claim Fraud Detection"  
    when  
        $claim : InsuranceClaim(incidentDate after [30d] )  
        // 事故日期在30天内的快速理赔  
    then  
        $claim.setFraudulent(true);  
        modify($claim);  
        System.out.println("快速理赔标记为可疑: " + $claim.getClaimId());  
end  
  
rule "Auto Approval for Small Claims"  
    when  
        $claim : InsuranceClaim(claimAmount <= 5000, fraudulent == false)  
    then  
        $claim.setApprovedAmount($claim.getClaimAmount());  
        modify($claim);  
        System.out.println("小额理赔自动批准: " + $claim.getClaimId());  
end  

流程定义中集成规则任务:

  
<process id="claimApprovalProcess" name="保险理赔审批流程">  
      
    <startEvent id="start" />  
      
    <!-- 规则任务:欺诈检测 -->  
    <businessRuleTask id="fraudDetection" name="欺诈检测"  
                      g:ruleFlowGroup="fraud-detection" />  
      
    <!-- 网关:基于欺诈检测结果路由 -->  
    <exclusiveGateway id="fraudDecision" />  
      
    <!-- 检测到欺诈 -->  
    <sequenceFlow id="fraudDetected" sourceRef="fraudDecision" targetRef="investigateFraud">  
        <conditionExpression>${claim.fraudulent == true}</conditionExpression>  
    </sequenceFlow>  
      
    <!-- 无欺诈 -->  
    <sequenceFlow id="noFraud" sourceRef="fraudDecision" targetRef="approvalDecision">  
        <conditionExpression>${claim.fraudulent == false}</conditionExpression>  
    </sequenceFlow>  
      
    <!-- 规则任务:自动理赔决策 -->  
    <businessRuleTask id="approvalDecision" name="理赔决策"  
                      g:ruleFlowGroup="claim-approval" />  
      
    <!-- 欺诈调查人工任务 -->  
    <userTask id="investigateFraud" name="欺诈调查"  
              g:assignee="fraud\_investigator" />  
      
    <endEvent id="end" />  
</process>  

深度集成原理

  1. 统一知识会话 :流程实例和规则引擎共享同一个KIE会话
  2. 事实对象同步 :流程变量自动作为事实插入规则引擎
  3. 规则流组 :通过规则流组控制规则执行顺序
  4. 动态规则更新 :支持运行时更新业务规则而不影响流程实例

有些小伙伴在处理复杂业务规则时,jBPM的这种集成模式特别有价值。

比如在风控场景中,反欺诈规则经常变化,使用jBPM可以独立更新规则而不需要修改流程定义。

六、JDEasyFlow:轻量级流程编排新星

JDEasyFlow是京东自研的轻量级流程编排组件,特点是简单、灵活、易扩展

它适用于不需要完整BPMN功能的简单场景。

核心原理

JDEasyFlow采用基于JSON的流程定义状态机引擎

它的设计理念是"约定优于配置",通过简单的节点定义实现灵活的流程编排。

架构特色

  • 基于JSON的声明式流程定义
  • 无数据库依赖,纯内存执行
  • 支持BPMN元素子集
  • 极低的学习成本

开源地址

GitHub: https://github.com/JDEasyFlow/jd-easyflow

示例:简单订单状态流转

JDEasyFlow特别适合简单的状态机场景:

首先引入依赖:

  
<dependency>  
    <groupId>com.jd.easyflow</groupId>  
    <artifactId>easyflow-flow</artifactId>  
    <version>1.2.0</version>  
</dependency>  

定义订单状态流程JSON:

  
{  
  "id": "order\_flow",  
"name": "订单状态流程",  
"nodes": [  
    {  
      "id": "created",  
      "name": "订单创建",  
      "start": true,  
      "post": {  
        "to": "paid"  
      }  
    },  
    {  
      "id": "paid",  
      "name": "已支付",  
      "action": {  
        "createExp": "new com.example.order.PaymentAction()"  
      },  
      "post": {  
        "to": "shipped"  
      }  
    },  
    {  
      "id": "shipped",  
      "name": "已发货",  
      "action": {  
        "createExp": "new com.example.order.ShipmentAction()"  
      },  
      "post": {  
        "to": "received"  
      }  
    },  
    {  
      "id": "received",  
      "name": "已收货",  
      "action": {  
        "createExp": "new com.example.order.ReceiveAction()"  
      },  
      "post": {  
        "to": "completed"  
      }  
    },  
    {  
      "id": "completed",  
      "name": "已完成"  
    },  
    {  
      "id": "cancelled",  
      "name": "已取消"  
    }  
  ]  
}  

Java节点动作实现:

  
// 支付节点动作  
@Component  
publicclass PaymentAction implements FlowNodeAction {  
      
    @Autowired  
    private PaymentService paymentService;  
      
    @Override  
    public Object execute(FlowRequest request, FlowContext context) {  
        String orderId = (String) request.getParam("orderId");  
          
        // 执行支付逻辑  
        PaymentResult result = paymentService.confirmPayment(orderId);  
          
        // 设置节点输出  
        Map<String, Object> resultData = new HashMap<>();  
        resultData.put("paymentId", result.getPaymentId());  
        resultData.put("paymentTime", result.getPaymentTime());  
        resultData.put("success", result.isSuccess());  
          
        logger.info("订单{}支付处理完成", orderId);  
          
        return resultData;  
    }  
}  
  
// 发货节点动作  
@Component  
publicclass ShipmentAction implements FlowNodeAction {  
      
    @Autowired  
    private LogisticsService logisticsService;  
      
    @Override  
    public Object execute(FlowRequest request, FlowContext context) {  
        String orderId = (String) request.getParam("orderId");  
          
        // 调用物流服务发货  
        ShipmentInfo shipment = logisticsService.createShipment(orderId);  
          
        Map<String, Object> resultData = new HashMap<>();  
        resultData.put("shipmentId", shipment.getShipmentId());  
        resultData.put("shipmentTime", shipment.getShipmentTime());  
        resultData.put("logisticsCompany", shipment.getCompany());  
          
        logger.info("订单{}发货完成,物流单号: {}", orderId, shipment.getShipmentId());  
          
        return resultData;  
    }  
}  

流程引擎配置和使用:

  
@Configuration  
publicclass EasyFlowConfig {  
      
    @Bean  
    public FlowEngine flowEngine() {  
        FlowEngineImpl flowEngine = new FlowEngineImpl();  
        flowEngine.setFlowPath("classpath:flows/order\_flow.json");  
        flowEngine.init();  
        return flowEngine;  
    }  
}  
  
@Service  
publicclass OrderFlowService {  
      
    @Autowired  
    private FlowEngine flowEngine;  
      
    // 执行订单流程  
    public void processOrder(String orderId, String action) {  
        Map<String, Object> params = new HashMap<>();  
        params.put("orderId", orderId);  
        params.put("action", action);  
          
        FlowParam flowParam = new FlowParam("order\_flow", params);  
          
        // 执行流程  
        FlowResult result = flowEngine.execute(flowParam);  
          
        if (result.isSuccess()) {  
            logger.info("订单流程执行成功: {}", result.getNodeIds());  
        } else {  
            logger.error("订单流程执行失败: {}", result.getMessage());  
            thrownew RuntimeException("流程执行失败: " + result.getMessage());  
        }  
    }  
      
    // 获取下一个可用节点  
    public List<String> getNextNodes(String orderId, String currentNode) {  
        Map<String, Object> params = new HashMap<>();  
        params.put("orderId", orderId);  
          
        FlowParam flowParam = new FlowParam("order\_flow", params);  
          
        // 解析流程定义,获取后续节点  
        return flowEngine.getNextNodes(flowParam, currentNode);  
    }  
}  

轻量级架构解析

  1. JSON定义 :通过简单的JSON结构定义节点和流转
  2. 无持久化 :纯内存执行,性能极高
  3. 插件化动作 :通过接口实现业务逻辑
  4. 条件支持 :支持简单的条件表达式路由

JDEasyFlow的这种设计特别适合服务编排简单状态机 场景。

有些小伙伴在微服务架构中需要编排多个服务调用,但又不想引入沉重的BPMN引擎,JDEasyFlow是完美选择。

七、五种工作流引擎全面对比

为了帮助大家更好地进行技术选型,我整理了这五种工作流引擎的详细对比:

| 特性维度 | Activiti | Flowable | Camunda | jBPM | JDEasyFlow | | --- | --- | --- | --- | --- | --- | | 学习曲线 | 中等 | 中等 | 较陡 | 较陡 | 简单 | | 性能 | 良好 | 优秀 | 优秀 | 良好 | 极佳 | | 功能完备性 | 高 | 高 | 很高 | 高 | 中等 | | 监控运维 | 基础 | 良好 | 优秀 | 良好 | 简单 | | 社区生态 | 活跃 | 活跃 | 活跃 | 活跃 | 一般 | | 云原生支持 | 基础 | 良好 | 优秀 | 良好 | 良好 | | 规则集成 | 基础 | 基础 | 良好 | 优秀 | 无 | | 适用场景 | 传统企业应用 | 高性能业务 | 微服务架构 | 规则密集型 | 轻量级编排 |

为了更直观地展示选型逻辑,我画了一个决策流程图:

picture.image

八、总结

下面我们来总结一下工作流引擎选型的一些建议:

  1. 传统企业级应用 :选择 Activiti ,生态成熟,文档丰富,遇到问题容易找到解决方案
  2. 高性能高并发场景 :选择 Flowable ,它在Activiti基础上做了大量性能优化
  3. 微服务架构 :选择 Camunda ,外部任务模式完美契合微服务理念,运维监控工具完善
  4. 规则密集型业务 :选择 jBPM ,与Drools规则引擎深度集成,适合风控、保险等场景
  5. 轻量级服务编排 :选择 JDEasyFlow ,简单灵活,学习成本低,无外部依赖

有些小伙伴在工作中可能会想:"能不能一个项目用多种工作流引擎?"

我的经验是:可以,但要明确边界

比如用Camunda管理核心业务流程,用JDEasyFlow做微服务内部编排。

最后记住:没有最好的工作流引擎,只有最合适的

选型时要综合考虑团队技术栈、业务场景、性能要求和运维能力。

最后欢迎加入苏三的星球,你将获得:SaaS点餐系统(DDD+多租户)、100万QPS短链系统(超过并发)、复杂的商城微服务系统(分布式)、苏三AI项目、刷题吧小程序、秒杀系统、商城系统、码猿简历网站、代码生成工具等9个项目的源代码、开发教程和技术答疑。 系统设计、性能优化、技术选型、底层原理、Spring源码解读、工作经验分享、痛点问题、面试八股文等多个优质专栏。

还有1V1免费修改简历、技术答疑、职业规划、送书活动、技术交流。

扫描下方二维码,可以加入星球:

picture.image

数量有限,先到先得。 目前星球已经更新了6100+篇优质内容,还在持续爆肝中.....

星球已经被官方推荐了3次,收到了小伙伴们的一致好评。戳我加入学习,已有2000+小伙伴加入学习。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
基于 ByteHouse 引擎的增强型数据导入技术实践
ByteHouse 基于自研 HaMergeTree,构建增强型物化 MySQL、HaKafka 引擎,实现数据快速集成,加速业务数据分析性能与效率,本次 talk 主要介绍物化 MySQL 与 HaKafka 数据导入方案和业务实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论