规则引擎之LiteFlow应用

官网地址: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 实体类
java 复制代码
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; // 折扣价格
}
java 复制代码
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 流程上下文
java 复制代码
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 流程启动节点
java 复制代码
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 {


    @Override
    public 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 满减策略节点
java 复制代码
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 {

    @Override
    public 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减去30
        if (amount.intValue() >= 200) {
            amount = amount.subtract(new BigDecimal(30));
        }
        log.info("满减后商品总价:{}", amount.floatValue());
        contextBean.getStrategyMap().put("FREE", amount);
    }
}
3.4 折扣策略节点
java 复制代码
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 {

    @Override
    public 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 确认优惠券策略节点
java 复制代码
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 {

    @Override
    public 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 确认邮费节点
java 复制代码
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 {
    @Override
    public 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 创建订单节点
java 复制代码
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 {
    @Override
    public void process() throws Exception {
        OrderProcessFlowContext contextBean = this.getContextBean(OrderProcessFlowContext.class);
        Order order = contextBean.getOrder();
        log.info("订单创建成功:{}", order);
    }
}

4. flow.el.xml 配置文件

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<flow>
    <chain name="orderChain">
        THEN(
        initOrderNode,
        WHEN(free,discount),
        confirmStrategyNode,
        confirmShippingCostNode,
        createOrderNode);
    </chain>
</flow>

5. 测试

java 复制代码
   @Resource
    private 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";
        }
    }

6.结果

相关推荐
GoodStudyAndDayDayUp3 分钟前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶34 分钟前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗41 分钟前
常用类晨考day15
java
骇客野人44 分钟前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
yuanbenshidiaos2 小时前
c++---------数据类型
java·jvm·c++
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
Lojarro2 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
莫名其妙小饼干2 小时前
网上球鞋竞拍系统|Java|SSM|VUE| 前后端分离
java·开发语言·maven·mssql
isolusion2 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp3 小时前
Spring-AOP
java·后端·spring·spring-aop