规则引擎之LiteFlow应用

news2025/6/27 7:20:05

 

 官网地址: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 {


    @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 满减策略节点
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 折扣策略节点
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  确认优惠券策略节点
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 确认邮费节点
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 创建订单节点
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 配置文件

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

5. 测试

   @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.结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1584025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TensorFlow学习之:深度学习基础

神经网络基础 神经网络是深度学习的核心&#xff0c;它们受人脑的结构和功能启发&#xff0c;能够通过学习大量数据来识别模式和解决复杂问题。神经网络的基本工作原理包括前向传播和反向传播两个阶段。 前向传播&#xff08;Forward Propagation&#xff09; 前向传播是神经…

微信小程序制作圆形进度条

微信小程序制作圆形进度条 1. 建立文件夹 选择一个目录建立一个文件夹&#xff0c;比如 mycircle 吧&#xff0c;另外把对应 page 的相关文件都建立出来&#xff0c;包括 js&#xff0c;json&#xff0c;wxml 和 wxcc。 2. 开启元件属性 在 mycircle.json中开启 component 属…

uniapp小程序中使用video视频播放卡顿

问题:在使用uniapp小程序的video视频播放,视频已经在播放了,但是进度条没走,还是卡顿的状态(测试ios能正常使用,安卓手机会出现此问题) 在网上找了很多方法,最多的说是用:custom-cache"false",试了并没有效果,看来和我问题不一样,后来用了个简单粗暴的方法,发现是有效…

docker 创建容器过程

结合下图&#xff0c;本文讨论docker 创建容器过程&#xff1a; START└── [用户通过Docker Client发出指令]└── (1) docker run 或 docker create 命令├── (2) Docker Client与Docker Daemon建立通信连接└── (3) Docker Daemon接收到创建容器请求├── (4) 检查…

密码学基础--搞清RFC和PKCS(1)

目录 1. CryptoDriver里KeyElement格式 2. 挖掘RFC标准 3.小结 昨天从生成密钥对开始逐步了解了公钥、证书等各种编码方式&#xff0c;今天继续趁热打&#xff0c;做一个理论知识汇总。 Ps:我只是标准的翻译搬运工。 1. CryptoDriver里KeyElement格式 在 CryptoKeyElemen…

实现鼠标在页面点击出现焦点及大十字星

近段时间&#xff0c;在完成项目进度情况显示时候&#xff0c;用户在操作鼠标时候&#xff0c;显示当鼠标所在位置对应时间如下图所示 代码实现步骤如下&#xff1a; 1.首先引用 jquery.1.7.js 2.再次引用raphael.js 3.然后引用graphics.js 4.最后引用mfocus.js 其中mfocu…

地理信息系统(ArcGIS)在水文水资源、水环境中的应用

刘老师&#xff08;副教授&#xff09;&#xff1a;来自北京重点高校资深专家&#xff0c;长期从事水资源与水环境、流域污染控制与管理、非点源模拟与控制、环境信息系统开发、环境遥感与GIS应用等领域的研究&#xff0c;发表多篇Sci论文、具有资深的技术底蕴和专业背景。 1、…

多张固定宽度元素,随着屏幕尺寸变化自动换行

背景&#xff1a;多张固定宽度元素&#xff0c;随着屏幕尺寸变化自动换行实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevic…

最好的 iPhone 解锁器解决方案功能、优点和缺点

现最受好评的 iPhone 解锁器&#xff0c;例如 奇客解锁、iPassGo 等。深入了解它们的优缺点和兼容性&#xff0c;以做出明智的决定。了解如何解锁 iPhone 并解决有关解锁方法、PIN 绕过和潜在风险的常见问题。 1、奇客手机解锁 奇客手机解锁是一款适用于 iOS 的多功能解锁工具…

Ubuntu-22.04安装VMware虚拟机并安装Windows10

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、VMware是什么&#xff1f;二、安装VMware1.注册VMware账号2.下载虚拟机3.编译vmmon&vmnet4.加载module5.安装bundle 三、安装Windows101.基础配置2.进阶…

RISC-V特权架构 - 中断注入

中断注入 1 中断注入的作用2 mip寄存器3 中断注入后的处理过程 本文属于《 RISC-V指令集基础系列教程》之一&#xff0c;欢迎查看其它文章。 1 中断注入的作用 中断注入&#xff0c;就是在M模式下&#xff0c;手动向S模式去产生一个中断。 比如&#xff1a;向mip寄存器的bit5…

为什么需要SOCKS代理?

在数字化时代&#x1f310;&#xff0c;随着网络安全威胁的不断演进和增加&#xff0c;保护个人隐私和数据安全成为了互联网用户的一大挑战&#x1f6e1;️。在寻求增强在线安全和隐私的解决方案时&#xff0c;SOCKS代理成为了一个关键的技术工具&#x1f511;。本文旨在详细探…

华为数通配置旁挂二层组网直接转发实验

配置旁挂二层组网直接转发示例 组网图形 组网需求 AC组网方式&#xff1a;旁挂二层组网。DHCP部署方式&#xff1a; AC作为DHCP服务器为AP分配IP地址。汇聚交换机SwitchB作为DHCP服务器为STA分配IP地址。业务数据转发方式&#xff1a;直接转发。 数据规划 表1 AC数据规划表 …

Linux JDK修改不生效

原JDK8&#xff0c;现需要切换为JDK11&#xff0c;环境变量已经修改为11&#xff0c;但java -version还是显示8。 ln -s -f /home/jdk-11.0.19/bin/java

数据结构——线性表(链式存储结构)

语言&#xff1a;C语言软件&#xff1a;Visual Studio 2022笔记书籍&#xff1a;数据结构——用C语言描述如有错误&#xff0c;感谢指正。若有侵权请联系博主 一、线性表的逻辑结构 线性表是n个类型相同的数据元素的有限序列&#xff0c;对n>0&#xff0c;除第一元素无直接…

Web3 的社会影响:数字社会的新时代

随着科技的不断进步和创新&#xff0c;人类社会正逐步进入数字化时代的新阶段。Web3 技术作为数字社会的重要组成部分&#xff0c;正在以前所未有的方式重塑着我们的社会生活和交往方式。本文将探讨 Web3 技术对社会的影响&#xff0c;以及它所带来的数字社会的新时代。 1. Web…

同旺科技 USB TO SPI / I2C 专业版 极限测试 ---- 写入数据

所需设备&#xff1a; 1、USB 转 SPI I2C 适配器&#xff1b;内附链接 备注&#xff1a;带EXCEL调试的只适用于专业版&#xff1b; 软件配置&#xff1a; 设置如下&#xff0c;写入32766个字节&#xff0c;单条指令&#xff0c;速率20Mhz; 32766个字节不是适配器的极限&am…

SpringBoot中的Redis的简单使用

在Spring Boot项目中使用Redis作为缓存、会话存储或分布式锁等组件&#xff0c;可以简化开发流程并充分利用Redis的高性能特性。以下是使用Spring Boot整合Redis的详细步骤&#xff1a; 1. 环境准备 确保开发环境中已安装&#xff1a; Java&#xff1a;用于编写和运行Spring…

Node.js常用快捷键

1.常用的终端命令&#xff1a; &#xff08;1&#xff09;del 文件名&#xff1a; 删除文件 &#xff08;2&#xff09;ipconfig: 查看IP命令 &#xff08;3&#xff09;mkdir 目录名 &#xff1a;在当前目录新建指定目录 &#xff08;4&#xff09;rd 目录名&#xff1a;在当前…

【JavaWeb】Day40.MySQL概述——多表设计(一对多)

多表设计 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种&#xff1a; 一对多(多…