前言

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

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

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

一、工作流引擎是什么?

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

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

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

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

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

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

image

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

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

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

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

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

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

核心原理

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

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

架构特点

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

开源地址

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自动维护任务状态,通过TaskQueryAPI查询待办
  4. 状态持久化:所有流程状态自动持久化到数据库,保证一致性

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

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

三、Flowable:Activiti的性能优化版

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

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

核心原理

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

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

架构改进

  1. 增强的异步执行器,支持批量操作
  2. 优化的执行树结构,减少数据库访问
  3. 更好的缓存管理和懒加载策略
  4. 原生支持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采用外部任务模式乐观锁并发控制。它的核心思想是将工作流引擎与业务服务解耦,通过外部任务队列实现松耦合集成。

架构特色

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

开源地址

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采用知识会话模式,将流程引擎和规则引擎统一在同一个会话中。

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

架构特色

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

开源地址

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的流程定义状态机引擎

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

架构特色

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

开源地址

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是完美选择。

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

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

image

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

image

八、总结

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

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

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

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

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

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

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

最后修改:2026 年 06 月 06 日
如果觉得我的文章对你有用,请随意赞赏