官网地址:LiteFlow
DEMO 整体结构
1.引入maven依赖
<dependency><groupId>com.yomahub</groupId><artifactId>liteflow-spring-boot-starter</artifactId><version>2.11.4.2</version> </dependency>
2. 配置yml
liteflow:#规则文件路径rule-source: config/flow.el.xml
3. 模拟商品订单流程,下单-->计算优惠->计算邮费->总价-> 创建订单
3.0 实体类
package com.example.demo.domain;import lombok.Data;import java.math.BigDecimal;
import java.util.List;/*** @author Jerry* @date 2024-04-10 16:15* 订单*/
@Data
public class Order {private String orderId; // 订单号private List<Product> productList; // 商品列表private BigDecimal amount; // 总价private BigDecimal shippingCost; // 折扣价格
}
package com.example.demo.domain;import lombok.AllArgsConstructor;
import lombok.Data;import java.math.BigDecimal;/*** @author Jerry* @date 2024-04-10 16:13*/
@Data
@AllArgsConstructor
public class Product {private String productType; // 商品类型private String productName; // 商品名称private BigDecimal price; // 商品价格
}
3.1 流程上下文
package com.example.demo.liteflow;import com.example.demo.domain.Order;
import com.example.demo.domain.Product;
import lombok.Data;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author Jerry* @date 2024-04-10 16:19* 订单流程规则上下文*/
@Data
public class OrderProcessFlowContext {private List<Product> productList = new ArrayList<>(); // 商品列表private Order order; // 订单private Map<String, BigDecimal> strategyMap = new HashMap<>(); // 优惠策略
}
3.2 流程启动节点
package com.example.demo.liteflow.node;import cn.hutool.core.lang.UUID;
import com.example.demo.domain.Order;
import com.example.demo.liteflow.OrderProcessFlowContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;/*** @author Jerry* @date 2024-04-10 16:08* 优惠券计算组件*/
@Slf4j
@Component
@LiteflowComponent(id = "initOrderNode", name = "流程启动节点") // id - 在流程中的名称
public class InitOrderNode extends NodeComponent {@Overridepublic void process() throws Exception {OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);Order order = new Order();order.setOrderId(UUID.fastUUID().toString());order.setProductList(contextBean.getProductList());contextBean.setOrder(order);log.info("流程启动");}
}
3.3 满减策略节点
package com.example.demo.liteflow.node.strategy;import com.example.demo.domain.Product;
import com.example.demo.liteflow.OrderProcessFlowContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
import java.util.List;/*** @author Jerry* @date 2024-04-10 16:30* 满减策略*/
@Slf4j
@Component
@LiteflowComponent(id = "free", name = "满减策略节点")
public class Free extends NodeComponent {@Overridepublic void process() throws Exception {OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);List<Product> productList = contextBean.getProductList();BigDecimal amount = new BigDecimal(0);for (Product product : productList) {amount = amount.add(product.getPrice());}// 满200减去30if (amount.intValue() >= 200) {amount = amount.subtract(new BigDecimal(30));}log.info("满减后商品总价:{}", amount.floatValue());contextBean.getStrategyMap().put("FREE", amount);}
}
3.4 折扣策略节点
package com.example.demo.liteflow.node.strategy;import com.example.demo.domain.Product;
import com.example.demo.liteflow.OrderProcessFlowContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;/*** @author Jerry* @date 2024-04-10 16:37*/
@Slf4j
@Component
@LiteflowComponent(id = "discount", name = "打折策略节点")
public class Discount extends NodeComponent {@Overridepublic void process() throws Exception {OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);List<Product> productList = contextBean.getProductList();BigDecimal amount = new BigDecimal(0);for (Product product : productList) {if ("零食".equals(product.getProductType())) {amount = amount.add(product.getPrice().multiply(new BigDecimal("0.8")));} else if ("电器".equals(product.getProductType())) {amount = amount.add(product.getPrice().multiply(new BigDecimal("0.6")));} else {amount = amount.add(product.getPrice());}amount = amount.setScale(2, RoundingMode.UP);log.info("折扣后商品总价:{}", amount.floatValue());contextBean.getStrategyMap().put("DISCOUNT", amount);}}
}
3.5 确认优惠券策略节点
package com.example.demo.liteflow.node;import com.example.demo.liteflow.OrderProcessFlowContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;/*** @author Jerry* @date 2024-04-10 16:44* 优惠券计算抵扣组件*/
@Slf4j
@Component
@LiteflowComponent(id = "confirmStrategyNode", name = "确认优惠券策略节点")
public class ConfirmStrategyNode extends NodeComponent {@Overridepublic void process() throws Exception {OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);Map<String, BigDecimal> strategyMap = contextBean.getStrategyMap();Map.Entry<String, BigDecimal> min = strategyMap.entrySet().stream().min(Map.Entry.comparingByValue()).get();log.info("优惠策略已确认:{}", min.getValue());contextBean.getOrder().setAmount(min.getValue());}
}
3.6 确认邮费节点
package com.example.demo.liteflow.node;import com.example.demo.domain.Order;
import com.example.demo.liteflow.OrderProcessFlowContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.math.BigDecimal;/*** @author Jerry* @date 2024-04-10 17:06* 邮费计算*/
@Slf4j
@Component
@LiteflowComponent(id = "confirmShippingCostNode", name = "确认邮费节点")
public class ConfirmShippingCostNode extends NodeComponent {@Overridepublic void process() throws Exception {OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);Order order = contextBean.getOrder();if (order.getAmount().intValue() > 68) {order.setShippingCost(new BigDecimal(0));} else {order.setShippingCost(new BigDecimal(10));}log.info("邮费已确认:{}", order.getShippingCost());}
}
3.7 创建订单节点
package com.example.demo.liteflow.node;import com.example.demo.domain.Order;
import com.example.demo.liteflow.OrderProcessFlowContext;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;/*** @author Jerry* @date 2024-04-10 17:11*/
@Slf4j
@Component
@LiteflowComponent(id = "createOrderNode", name = "创建订单节点")
public class CreateOrderNode extends NodeComponent {@Overridepublic void process() throws Exception {OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);Order order = contextBean.getOrder();log.info("订单创建成功:{}", order);}
}
4. flow.el.xml 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<flow><chain name="orderChain">THEN(initOrderNode,WHEN(free,discount),confirmStrategyNode,confirmShippingCostNode,createOrderNode);</chain>
</flow>
5. 测试
@Resourceprivate FlowExecutor flowExecutor;@GetMapping("liteFlow")public String testLiteFlow() {OrderProcessFlowContext processFlowContext = new OrderProcessFlowContext();processFlowContext.getProductList().add(new Product("零食", "辣条", new BigDecimal(50)));processFlowContext.getProductList().add(new Product("电器", "洗衣机", new BigDecimal(200)));LiteflowResponse response = flowExecutor.execute2Resp("orderChain", null, processFlowContext);OrderProcessFlowContext context = response.getContextBean(OrderProcessFlowContext.class);if (response.isSuccess()) {return "success :" + JSONUtil.toJsonStr(context.getOrder());} else {return "error";}}