规则引擎之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 实体类
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";}}

6.结果

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql数据库备份脚本.sh

mysql数据库备份脚本.sh #!/bin/bash #备份路径 BAKDIR/home/peter/date %Y-%m-%d #要备份的数据库 MYSQLDBtest #使用哪个用户备份 MYSQLUSRroot #判断是否是root用户执行此脚本 if [ $UID -ne 0 ] then echo This scripts must use the root user!!! sleep 2 exit…

HDFS [MSST‘10] 论文阅读笔记

原论文:The Hadoop Distributed File System (MSST’10) HDFS关键技术要点概览 设计目标:HDFS旨在可靠地存储大型数据集,并以高带宽流式传输这些数据集到用户应用程序。它通过在大量服务器上分布存储和计算资源,使得资源可以随着需求的增长而扩展,同时保持经济高效。架构组…

24年权威数学建模报名通知汇总(含妈妈杯、国赛、美赛、电工杯、数维杯、五一数模、深圳杯......)

1、MathorCup比赛 报名时间&#xff1a;2024年4月11日中午12点&#xff08;周四&#xff09; 比赛开始时间&#xff1a;2024年4月12日上午8时&#xff08;周五&#xff09; 比赛结束时间&#xff1a;2024年4月16日上午9时&#xff08;周二&#xff09; 报名费用&#xff1a…

HarmonyOS 开发-Worker子线程中解压文件

介绍 本示例介绍在Worker 子线程使用ohos.zlib 提供的zlib.decompressfile接口对沙箱目录中的压缩文件进行解压操作&#xff0c;解压成功后将解压路径返回主线程&#xff0c;获取解压文件列表。 效果图预览 使用说明 点击解压按钮&#xff0c;解压test.zip文件&#xff0c;显…

基于springboot实现医院管理系统项目【项目源码+论文说明】

基于springboot实现医院管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系…

RabbitMQ如何保证消息的幂等性???

在RabbitMQ中&#xff0c;保证消费者的幂等性主要依赖于业务设计和实现&#xff0c;而非RabbitMQ本身提供的一种直接功能。 在基于Spring Boot整合RabbitMQ的场景下&#xff0c;要保证消费者的幂等性&#xff0c;通常需要结合业务逻辑设计以及额外的技术手段来实现。以下是一个…

Redis的双写一致性问题

双写一致性问题 1.先删除缓存或者先删除数据库都可能出现脏数据。 2.删除两次缓存&#xff0c;可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离&#xff0c;读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…

【CVE复现计划】CVE-2024-0195

CVE-2024-0195 简介&#xff1a; SpiderFlow是新一代开源爬虫平台&#xff0c;以图形化方式定义爬虫流程&#xff0c;不写代码即可完成爬虫。基于springbootlayui开发的前后端不分离,也可以进行二次开发。该系统/function/save接口存在RCE漏洞&#xff0c;攻击者可以构造恶意命…

蓝桥杯加训

1.两只塔姆沃斯牛&#xff08;模拟&#xff09; 思路&#xff1a;人和牛都记录三个数据&#xff0c;当前坐标和走的方向&#xff0c;如果人和牛的坐标和方向走重复了&#xff0c;那就说明一直在绕圈圈&#xff0c;无解 #include<iostream> using namespace std; const i…

评论发布完整篇(react版)

此篇文章阐述评论的最新、最热之间的tab标签切换&#xff08;包括当前所在tab标签的高亮显示问题&#xff09;&#xff1b;当前评论的删除&#xff1b;除此之外还延伸了用户的评论实时发布功能。其中最新tab标签所展示的内容是根据当前评论点赞数来进行排序&#xff0c;点赞数量…

人工智能前沿成科技竞争新高地

以下文章来源&#xff1a;经济参考报 近日&#xff0c;首届中国具身智能大会&#xff08;CEAI 2024&#xff09;在上海举行。作为人工智能领域的前沿热点&#xff0c;具身智能正逐步走进现实&#xff0c;成为当前全球科技竞争的新高地、未来产业的新赛道、经济发展的新引擎。 “…

厂房起火3D消防灭火安全救援模拟演练

深圳VR公司华锐视点依托前沿的VR虚拟现实制作、三维仿真和图形图像渲染技术&#xff0c;将参训者带入栩栩如生的火灾现场。佩戴VR头盔&#xff0c;参训者将真切体验火势蔓延的紧张与危机&#xff0c;身临其境地感受火灾的恐怖。 并且消防安全VR虚拟现实演练系统精心模拟了住宅、…

linux网络服务学习(6):多路径multipath解决iscsi多网卡识别错误问题

1.什么是多路径 1.1路径 物理层面一条数据的访问通道 访问方式&#xff1a; &#xff08;1&#xff09;以太网卡双绞网线以太网交换机 &#xff08;2&#xff09;HBA光纤卡光纤线光纤交换机 访问过程&#xff1a; &#xff08;1&#xff09;冗余链路failover&#xff1a…

Linux学习-网络TCP

TCP通信 TCP发端: socket connect send recv close TCP收端: socket bind listen accept send recv close 1.connect int connect(int sockfd, const struct sockaddr *addr, socklen_t …

德勤:《中国AI智算产业2024年四大趋势》

2023年《数字中国建设整体布局规划》的发布&#xff0c;明确了数字中国是构建数字时代竞争优势的关键支撑&#xff0c;是继移动互联网时代以来经济增长新引擎。当我们谈论数字中国的构建&#xff0c;不仅仅是在讨论一个国家级的技术升级&#xff0c;而是关乎如何利用数字技术来…

显示学习1(基于树莓派Pico) -- 基础

先上图为敬。 驱动的是0.96寸的OLED&#xff0c;SSD1315。使用的I2C接口驱动。 有一说一树莓派Pico用来学习底层真的太好了&#xff0c;没有之一。首先是价格便宜&#xff0c;10块钱包邮还要什么自行车。然后底层封装很完备&#xff0c;接近闭源。最后是用的python&#xff0c…

堆放砖块-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第47讲。 堆放砖块&#xf…

RuntimeError: Error(s) in loading state_dict for ZoeDepth解决方案

本文收录于《AI绘画从入门到精通》专栏,订阅后可阅读专栏内所有文章,专栏总目录:点这里。 大家好,我是水滴~~ 本文主要介绍在 Stable Diffusion WebUI 中使用 ControlNet 的 depth_zoe 预处理器时,出现的 RuntimeError: Error(s) in loading state_dict for ZoeDepth 异常…

TypeScript系列之-基本类型画图讲解

JS的类型(8)&#xff1a; null undefined string number boolean bigint symbol object&#xff08;含 Array, Function,Date.....&#xff09; TS的类型(87): 以上所有&#xff0c;加上 void, never, enum, unknown, any 再加上自定义类型 type interface 上一节我们说…

Google 发布 CodeGemma:7B 力压 CodeLLaMa-13B

刚刚发布&#xff01;Google 带来了新的 Gemma 家族成员&#xff0c;CodeGemma&#xff0c;这是基于预训练的 Gemma-2B 和 Gemma-7B 的代码生成模型。 其上下文窗口长度为8K&#xff0c;在另外 500 B 个主要由英语、数学和代码组成的 token 上进行了训练&#xff0c;改进了逻辑…