Spring Boot 3 整合 LiteFlow:轻量级流程编排框架学习
Spring Boot 3 整合 LiteFlow:轻量级流程编排框架学习
前言
在现代企业级应用开发中,复杂的业务逻辑往往涉及多个步骤和条件判断,传统的硬编码方式容易导致代码耦合度高、维护困难。LiteFlow作为一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑。
什么是LiteFlow
LiteFlow是一个轻量级、高性能的组件式流程编排框架,主要特点包括:
- 组件化设计:将复杂业务逻辑拆分为独立的组件,提高代码复用性
- 规则驱动:通过配置文件定义流程规则,支持热加载
- 高性能:基于责任链模式,执行效率高
- 易扩展:支持多种节点类型(普通节点、条件节点、选择节点等)
- Spring友好:与Spring Boot深度集成,支持依赖注入
核心概念
1. 节点类型
- 普通节点(COMMON):执行具体业务逻辑
- 条件节点(IF):根据条件判断执行不同分支
- 选择节点(SWITCH):根据返回值选择执行路径
- 循环节点(FOR/WHILE):支持循环执行
2. 流程表达式
LiteFlow使用EL表达式定义流程:
THEN(a, b, c):顺序执行WHEN(a, b, c):并行执行IF(x, a, b):条件执行SWITCH(x).TO(a, b, c):选择执行
项目搭建
1. 添加依赖
在pom.xml中添加LiteFlow依赖:
<dependencies><!-- Spring Boot 3 Web Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- LiteFlow Spring Boot Starter --><dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.11.0</version></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>
2. 配置文件
在application.yml中配置LiteFlow:
liteflow:# 规则文件路径,支持多种格式:xml、json、ymlrule-source: config/*.xml
实战案例:订单处理流程
以一个电商订单处理流程为例,展示LiteFlow的使用方法。流程图如下:

1. 定义上下文对象
LiteFlow中的上下文(Context)是一个非常重要的概念,它是整个流程执行过程中的数据共享和传递的桥梁。上下文可以理解为流程中的“全局变量”或“共享数据区”,它存储了流程执行过程中需要用到的各种数据。这些数据可以是流程参数、业务数据、中间结果等。
LiteFlow中的每个组件都可以访问上下文,并从中获取所需的数据或将数据存入上下文中。组件之间通过上下文进行数据交换,而不需要直接相互调用或传递参数。这种设计方式降低了组件之间的耦合度,提高了流程的灵活性和可维护性。
首先创建订单上下文,用于在各个组件间传递数据:
package com.example.entity;import lombok.Data;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;@Data
@Accessors(chain = true)
public class OrderContext {private String orderId;private String orderType;private List<String> processData = new ArrayList<>();
}
2. 创建业务组件
在LiteFlow中,业务逻辑被拆分为独立的组件,每个组件负责处理特定的业务功能。通过@LiteflowMethod定义组件内直接的节点方法。@LiteflowMethod注解则用于在组件类中声明可以被LiteFlow框架调用的方法。这个注解会指定该方法在流程中的节点类型(如普通节点、条件节点等)以及节点的一些属性(如节点ID、节点名称等)。在流程执行时,LiteFlow框架会根据流程定义中节点的配置来调用相应的组件方法,从而完成业务流程的执行,其中node_id的值即规则编排文件中表达式中对应的nodeId。
SWITCH组件详解
SWITCH组件的主要功能是在执行流程时根据预定义的条件进行分支选择。它通常用于处理流程中的决策点,类似于编程语言中的switch语句。在我们的订单处理场景中,SWITCH组件根据订单类型决定执行哪个流程节点:
- 如果是ToC订单(即orderType=1),就会走to_c流程
- 如果是ToB订单(即orderType=2),就会走to_b流程
这种设计的优势在于:
- 解耦业务逻辑:不同类型的订单处理逻辑完全分离,互不影响
- 易于扩展:新增订单类型时,只需添加新的处理分支即可
- 提高可维护性:每个分支的逻辑独立,便于调试和维护
业务节点组件设计
接下来我们需要定义处理订单的各业务节点。我们按照业务逻辑或者流程节点进行拆分成三个组件类:
- ToCHandlerCmp:专门处理ToC订单的组件类
- ToBHandlerCmp:专门处理ToB订单的组件类
- CommonHandleCmp:公共逻辑组件,包含可复用的业务节点
公共组件(CommonHandleCmp)
公共组件定义一些相同业务的处理节点,以便不同流程可以复用这些节点。同时也可以定义一些逻辑条件的节点,比如IF组件节点、SWITCH组件节点。在我们的案例中,公共组件包含:
- SWITCH节点(order_x):根据订单类型选择执行路径
- IF节点(order_k):判断是否为VIP订单
- 通用处理节点(order_c、order_h):所有订单都需要执行的公共逻辑
package com.example.liteflow;import com.example.entity.OrderContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;@Slf4j
@LiteflowComponent
public class CommonHandleCmp {@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_SWITCH, nodeType = NodeTypeEnum.SWITCH, nodeId = "order_x", nodeName = "获取订单链路")public String processOrderType(NodeComponent nodeComponent){Integer orderCode = nodeComponent.getRequestData();return OrderTypeEnum.getChainId(orderCode);}@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_c", nodeName = "CNodeComponent")public void processC(NodeComponent nodeComponent){OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("CNodeComponent");log.info("执行公共处理逻辑C");}@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_IF, nodeType = NodeTypeEnum.IF, nodeId = "order_k", nodeName = "KNodeComponent")public boolean processK(NodeComponent nodeComponent){OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("KNodeComponent");String orderType = orderContext.getOrderType();log.info("判断是否为VIP订单: {}", orderType);return "vip".equals(orderType);}@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_h", nodeName = "HNodeComponent")public void processH(NodeComponent nodeComponent) {OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("HNodeComponent");log.info("执行最终处理逻辑H");}@AllArgsConstructorenum OrderTypeEnum{TO_C(1, "to_c"),TO_B(2, "to_b");public final Integer code;public final String chainId;public static String getChainId(Integer code){return Arrays.stream(OrderTypeEnum.values()).filter(orderTypeEnum -> orderTypeEnum.code.equals(code)).findFirst().map(e -> e.chainId).orElseThrow(() -> new RuntimeException("不支持的订单类型"));}}
}
ToC订单处理组件(ToCHandleCmp)
ToC订单处理组件专门负责处理面向消费者(To Consumer)的订单业务逻辑。在这个组件中,我们定义了ToC订单特有的处理节点:
这些节点只在ToC订单流程中被调用,体现了组件化设计的优势。
package com.example.liteflow;import com.example.entity.OrderContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.extern.slf4j.Slf4j;
import java.util.List;@Slf4j
@LiteflowComponent
public class ToCHandleCmp {@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_a", nodeName = "ANodeComponent")public void processA(NodeComponent nodeComponent){OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("ANodeComponent");log.info("执行ToC订单初始化逻辑A");}@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_d", nodeName = "DNodeComponent")public void processD(NodeComponent nodeComponent){OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("DNodeComponent");log.info("执行VIP订单特殊处理逻辑D");}@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_f", nodeName = "FNodeComponent")public void processF(NodeComponent nodeComponent) {OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("FNodeComponent");log.info("执行VIP订单后续处理逻辑F");}
}
ToB订单处理组件(ToBHandleCmp)
ToB订单处理组件专门负责处理面向企业(To Business)的订单业务逻辑。企业订单通常具有不同的处理规则和业务流程:
package com.example.liteflow;import com.example.entity.OrderContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.annotation.LiteflowMethod;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.enums.LiteFlowMethodEnum;
import com.yomahub.liteflow.enums.NodeTypeEnum;
import lombok.extern.slf4j.Slf4j;
import java.util.List;@Slf4j
@LiteflowComponent
public class ToBHandleCmp {@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_b", nodeName = "BNodeComponent")public void processB(NodeComponent nodeComponent){OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("BNodeComponent");log.info("执行ToB订单初始化逻辑B");}@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS, nodeType = NodeTypeEnum.COMMON, nodeId = "order_e", nodeName = "ENodeComponent")public void processE(NodeComponent nodeComponent) {OrderContext orderContext = nodeComponent.getContextBean(OrderContext.class);List<String> processData = orderContext.getProcessData();processData.add("ENodeComponent");log.info("执行普通订单处理逻辑E");}
}
3. 配置流程规则
流程规则是LiteFlow的核心,它定义了各个组件的执行顺序和条件。在我们的订单处理场景中,流程规则体现了以下业务逻辑:
- 主流程:首先通过SWITCH组件根据订单类型选择对应的处理分支
- ToC流程:执行ToC订单初始化 → 公共处理 → VIP判断分支 → 最终处理
- ToB流程:执行ToB订单初始化 → 公共处理 → VIP判断分支 → 最终处理
- 条件分支:根据是否为VIP订单执行不同的处理逻辑
在src/main/resources/config/liteflow.xml中定义流程规则:
<?xml version="1.0" encoding="UTF-8"?>
<flow><chain name="order_handle">// 定义一个IF节点处理VIP订单分支逻辑// 如果order_k返回true(VIP订单),执行order_d和order_f// 如果order_k返回false(普通订单),执行order_eorder_if = IF(order_k, THEN(order_d, order_f), order_e);// 定义ToC订单的处理流程,用id标识流程为"to_c"// 顺序执行:ToC初始化 → 公共处理 → VIP判断分支to_c = THEN(order_a, order_c, order_if).id("to_c");// 定义ToB订单的处理流程,用id标识流程为"to_b" // 顺序执行:ToB初始化 → 公共处理 → VIP判断分支to_b = THEN(order_b, order_c, order_if).id("to_b");// 主流程:先通过SWITCH选择订单类型分支,最后执行公共结束逻辑// SWITCH(order_x)会根据返回值选择执行to_c或to_b流程THEN(SWITCH(order_x).TO(to_c, to_b), order_h);</chain>
</flow>
流程规则解析:
order_if:定义了VIP订单的条件分支,通过IF组件判断订单类型to_c和to_b:分别定义了ToC和ToB订单的完整处理流程- 主流程:使用SWITCH组件实现订单类型的路由分发,最后统一执行结束处理
4. 创建控制器
控制器作为流程的入口点,负责接收HTTP请求并触发LiteFlow流程执行。在我们的设计中:
- 通过路径参数
orderType指定订单类型(1=ToC,2=ToB) - 请求体包含订单上下文信息
- 使用FlowExecutor执行指定的流程链
- 返回处理后的订单上下文数据
package com.example.controller;import com.example.entity.OrderContext;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/order")
@RequiredArgsConstructor
public class OrderController {private final FlowExecutor flowExecutor;@PostMapping("/process/{orderType}")public OrderContext processOrder(@PathVariable Integer orderType, @RequestBody OrderContext orderContext) {// 执行流程LiteflowResponse response = flowExecutor.execute2Resp("order_handle", orderType, orderContext);if (response.isSuccess()) {return response.getContextBean(OrderContext.class);} else {throw new RuntimeException("订单处理失败: " + response.getMessage());}}
}
5. 测试用例
package com.example.service;import com.alibaba.fastjson.JSON;
import com.example.entity.OrderContext;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class LiteFlowTest {@Autowiredprivate FlowExecutor flowExecutor;@Testpublic void testToCOrder() {OrderContext orderContext = new OrderContext();orderContext.setOrderId("1234");orderContext.setOrderType("vip");LiteflowResponse response = flowExecutor.execute2Resp("order_handle", 1, orderContext);orderContext = response.getContextBean(OrderContext.class);System.out.println("ToC VIP订单处理结果: " + JSON.toJSONString(orderContext));// 预期执行顺序: ANodeComponent -> CNodeComponent -> KNodeComponent -> DNodeComponent -> FNodeComponent -> HNodeComponent}@Testpublic void testToBOrder() {OrderContext orderContext = new OrderContext();orderContext.setOrderId("5678");orderContext.setOrderType("normal");LiteflowResponse response = flowExecutor.execute2Resp("order_handle", 2, orderContext);orderContext = response.getContextBean(OrderContext.class);System.out.println("ToB普通订单处理结果: " + JSON.toJSONString(orderContext));// 预期执行顺序: BNodeComponent -> CNodeComponent -> KNodeComponent -> ENodeComponent -> HNodeComponent}
}
异常处理
可以为链路配置异常处理:
@LiteflowMethod(value = LiteFlowMethodEnum.PROCESS_EXCEPTION)
public void processException(NodeComponent nodeComponent) {Exception exception = nodeComponent.getException();log.error("流程执行异常", exception);// 处理异常逻辑
}
数据传递
组件间可以通过多种方式传递数据:
// 通过上下文传递
OrderContext context = nodeComponent.getContextBean(OrderContext.class);// 通过请求数据传递
String requestData = nodeComponent.getRequestData();// 通过slot传递
nodeComponent.setSlot("key", "value");
String value = nodeComponent.getSlot("key");
文章参考:参考学习1
