规则引擎之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.结果

相关推荐
qq_441996057 分钟前
Mybatis官方生成器使用示例
java·mybatis
巨大八爪鱼14 分钟前
XP系统下用mod_jk 1.2.40整合apache2.2.16和tomcat 6.0.29,让apache可以同时访问php和jsp页面
java·tomcat·apache·mod_jk
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
计算机-秋大田2 小时前
基于微信小程序的养老院管理系统的设计与实现,LW+源码+讲解
java·spring boot·微信小程序·小程序·vue
魔道不误砍柴功4 小时前
简单叙述 Spring Boot 启动过程
java·数据库·spring boot
失落的香蕉4 小时前
C语言串讲-2之指针和结构体
java·c语言·开发语言
枫叶_v4 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
wclass-zhengge4 小时前
SpringCloud篇(配置中心 - Nacos)
java·spring·spring cloud
路在脚下@4 小时前
Springboot 的Servlet Web 应用、响应式 Web 应用(Reactive)以及非 Web 应用(None)的特点和适用场景
java·spring boot·servlet
黑马师兄4 小时前
SpringBoot
java·spring