Springboot集成Easy Rules引擎,实现一个商品优惠券系统

news/2025/1/17 6:58:55/

Easy Rules是一个轻量级的Java规则引擎,它允许开发者将业务规则从代码中解耦出来,使规则的管理和执行更加灵活。

现在让我们一起利用Spring Boot结合Easy Rules和MyBatis技术栈,可以实现一个高效且易于维护的优惠券系统例子。

1. 添加依赖项

在 pom.xml 文件中确保包含以下依赖项:

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis Framework --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.1</version></dependency><!-- MySQL Connector --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- Easy Rules Core --><dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-core</artifactId><version>4.4.0</version></dependency><!-- Easy Rules Support for Spring --><dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-support-spring</artifactId><version>4.4.0</version></dependency><!-- Lombok (Optional, for reducing boilerplate code) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Test Dependencies --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>

2. 配置 MyBatis 和数据库连接

在 application.properties 文件中配置数据库连接信息和 MyBatis 设置:

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/coupon_system?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver# MyBatis 配置
mybatis.type-aliases-package=com.example.couponsystemdb.model
mybatis.mapper-locations=classpath*:mapper/*.xml

3. 定义业务实体类

我们需要定义一些业务实体类来表示购物车、商品和优惠券信息。

ShoppingCart.java

package com.example.couponsystemdb.model;import lombok.Data;
import java.util.ArrayList;
import java.util.List;@Data
publicclass ShoppingCart {privatedouble totalPrice = 0; // 购物车总价格privatefinal List<Item> items = new ArrayList<>(); // 商品列表/*** 向购物车添加商品* @param item 商品对象*/public void addItem(Item item) {items.add(item);totalPrice += item.getPrice();}/*** 应用折扣* @param discount 折扣比例(例如 0.10 表示 10% 折扣)*/public void applyDiscount(double discount) {totalPrice -= totalPrice * discount;}
}

Item.java

package com.example.couponsystemdb.model;import lombok.Data;@Data
publicclass Item {private String name; // 商品名称private String category; // 商品类别privatedouble price; // 商品价格/*** 构造函数* @param name 商品名称* @param category 商品类别* @param price 商品价格*/public Item(String name, String category, double price) {this.name = name;this.category = category;this.price = price;}
}

CouponRule.java

这个类用于从数据库加载规则信息。

package com.example.couponsystemdb.model;import lombok.Data;@Data
public class CouponRule {private Long id; // 规则IDprivate String ruleName; // 规则名称private String description; // 规则描述private String conditionExpression; // 条件表达式private String actionExpression; // 动作表达式
}

4. 创建数据库表和初始化数据

创建一个名为 coupon_system 的数据库,并在其中创建 coupon_rule 表。然后插入一些初始规则数据。

SQL 脚本

CREATE DATABASE coupon_system;USE coupon_system;CREATETABLE coupon_rule (idBIGINT AUTO_INCREMENT PRIMARY KEY,rule_name VARCHAR(255) NOTNULL,description TEXT,condition_expression TEXTNOTNULL,action_expression TEXTNOTNULL
);INSERTINTO coupon_rule (rule_name, description, condition_expression, action_expression) VALUES
('Total Price Discount Rule', 'Offers a 10% discount if the total price exceeds 1000',
'cart.getTotalPrice() > 1000',
'cart.applyDiscount(0.10); System.out.println("Applied 10% discount for total price exceeding 1000");'),('Category Discount Rule', 'Offers an additional 5% discount on Electronics category',
'cart.getItems().stream().anyMatch(item -> item.getCategory().equals("Electronics"))',
'cart.applyDiscount(0.05); System.out.println("Applied 5% discount for purchasing electronics");');

5. 定义动态规则

我们将使用 Easy Rules 的 DynamicRule 类来从数据库加载规则并执行。

DynamicCouponRule.java

package com.example.couponsystemdb.rule;import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.core.DynamicRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
publicclass DynamicCouponRule extends DynamicRule {@Autowiredprivate CouponService couponService;/*** 评估条件* @param facts 事实对象* @return 是否满足条件* @throws Exception 异常*/@Override@Conditionpublic boolean evaluate(Facts facts) throws Exception {returnsuper.evaluate(facts);}/*** 执行动作* @param facts 事实对象* @throws Exception 异常*/@Override@Actionpublic void execute(Facts facts) throws Exception {super.execute(facts);}/*** 从数据库设置规则* @param ruleId 规则ID*/public void setRuleFromDatabase(Long ruleId) {CouponRule couponRule = couponService.getCouponRuleById(ruleId);setName(couponRule.getRuleName());setDescription(couponRule.getDescription());setConditionExpression(couponRule.getConditionExpression());setActionExpression(couponRule.getActionExpression());}
}

6. 配置规则引擎

我们需要配置规则引擎并将规则注册到 Spring 上下文中。

EasyRulesConfig.java

package com.example.couponsystemdb.config;import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
publicclass EasyRulesConfig {/*** 配置规则引擎* @return 规则引擎实例*/@Beanpublic RulesEngine rulesEngine() {returnnew DefaultRulesEngine();}
}

7. 创建 Service 层

创建一个服务层来处理与数据库的交互。

CouponService.java

package com.example.couponsystemdb.service;import com.example.couponsystemdb.mapper.CouponRuleMapper;
import com.example.couponsystemdb.model.CouponRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
publicclass CouponService {@Autowiredprivate CouponRuleMapper couponRuleMapper;/*** 根据规则ID获取规则* @param id 规则ID* @return 规则对象*/public CouponRule getCouponRuleById(Long id) {return couponRuleMapper.selectById(id);}
}

8. 创建 Mapper 接口

使用 MyBatis 映射器接口来操作数据库。

CouponRuleMapper.java

package com.example.couponsystemdb.mapper;import com.example.couponsystemdb.model.CouponRule;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface CouponRuleMapper {/*** 根据规则ID查询规则* @param id 规则ID* @return 规则对象*/@Select("SELECT * FROM coupon_rule WHERE id = #{id}")CouponRule selectById(Long id);
}

9. 编写主应用程序类

最后,在主应用程序类中使用规则引擎来处理购物车中的商品。

CouponSystemApplication.java

package com.example.couponsystemdb;import com.example.couponsystemdb.model.ShoppingCart;
import com.example.couponsystemdb.model.Item;
import com.example.couponsystemdb.rule.DynamicCouponRule;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
publicclass CouponSystemApplication implements CommandLineRunner {@Autowiredprivate RulesEngine rulesEngine; // 规则引擎@Autowiredprivate DynamicCouponRule dynamicCouponRule; // 动态规则@Autowiredprivate CouponService couponService; // 优惠券服务public static void main(String[] args) {SpringApplication.run(CouponSystemApplication.class, args);}/*** 应用启动时运行的方法* @param args 命令行参数* @throws Exception 异常*/@Overridepublic void run(String... args) throws Exception {ShoppingCart cart = new ShoppingCart(); // 创建购物车cart.addItem(new Item("Laptop", "Electronics", 1200)); // 添加商品cart.addItem(new Item("Book", "Books", 30)); // 添加商品Facts facts = new Facts(); // 创建事实对象facts.put("cart", cart); // 将购物车放入事实对象Rules rules = new Rules(); // 创建规则集合// 从数据库加载规则并注册到规则引擎Long[] ruleIds = {1L, 2L}; // 数据库中的规则IDfor (Long ruleId : ruleIds) {dynamicCouponRule.setRuleFromDatabase(ruleId); // 从数据库设置规则rules.register(dynamicCouponRule); // 注册规则}rulesEngine.fire(rules, facts); // 执行规则引擎System.out.println("Final price after discounts: " + cart.getTotalPrice()); // 输出最终价格}
}

运行应用程序

保存所有文件并在终端中运行以下命令启动应用程序:

mvn spring-boot:run

你应该会看到以下输出:

Applied 10% discount for total price exceeding 1000
Applied 5% discount for purchasing electronics
Final price after discounts: 1071.0

总结

这个示例展示了如何在 Spring Boot 应用程序中集成 Easy Rules 和 MyBatis,以便通过数据库灵活配置优惠券规则。通过这种方式,你可以在不修改代码的情况下添加新的规则。以下是关键点总结:

  1. 数据库配置:使用 MyBatis 和 MySQL 来存储和管理规则。

  2. 动态规则:使用 Easy Rules 的 DynamicRule 类来加载和执行从数据库获取的规则。

  3. 服务层:通过服务层来处理与数据库的交互。

  4. 规则引擎配置:配置规则引擎并注册动态规则。

关注我!Java从此不迷路!

31002605457a4fb52d495fdcc290262c.gif

95c0da44ba1406f80ff15af863bf7655.jpeg


http://www.ppmy.cn/news/1563824.html

相关文章

【云岚到家】-day02-客户管理-认证授权

第二章 客户管理 1.认证模块 1.1 需求分析 1.基础概念 一般情况有用户交互的项目都有认证授权功能&#xff0c;首先我们要搞清楚两个概念&#xff1a;认证和授权 认证: 就是校验用户的身份是否合法&#xff0c;常见的认证方式有账号密码登录、手机验证码登录等 授权:则是该用…

【Ubuntu与Linux操作系统:十二、LAMP平台与PHP开发环境】

第12章 LAMP平台与PHP开发环境 12.1 LAMP安装与配置 LAMP简介 LAMP 是一种经典的开源 Web 开发平台&#xff0c;代表 Linux&#xff08;操作系统&#xff09;、Apache&#xff08;Web 服务器&#xff09;、MySQL&#xff08;数据库管理系统&#xff09;和 PHP&#xff08;脚本…

【嵌入式——Linux】Ubuntu网络环境配置

本文描述的是在VMWare中配置网络&#xff0c;使其可以与板子互通&#xff0c;方便之后的嵌入式Linux开发。 单击“编辑”然后选择“虚拟网络编辑器 单击更改设置 选择VMnet0 类型选择桥接模式&#xff0c;自动桥接 如果想要桥接至某一个网卡&#xff0c;可以在下方自动处选择…

使用贪心算法解决最小生成树问题

大家好&#xff0c;我是 V 哥。今天跟大家聊一聊贪心算法问题&#xff0c;因为遇到这个面试题&#xff0c;问贪心算法解决最小生成树是怎么设计的&#xff0c;以及如何应用&#xff1f;好家伙&#xff0c;这面试官一上来就不按套路出牌&#xff0c;直接上难度&#xff0c;如果你…

mysql绿色版卸载详细教程

本文主要讲解如何卸载mysql绿色版&#xff1a; 用管理员权限打开cmd窗口&#xff0c;切换到mysql安装目录的bin目录下&#xff0c;如下图&#xff0c;执行命令【net stop mysql】以停止mysql服务。 除了上述命令行停止mysql服务的方法&#xff0c;也可以在服务界面通过右键菜单…

Git 规范

Commit 提交规范 Git commit 规范是一种约定俗成的方式&#xff0c;用于规范化提交信息的格式和内容。 遵循 Git commit 规范可以提高代码提交信息的可读性和可维护性&#xff0c;方便团队成员之间的沟通和代码审查。 同时&#xff0c;还可以利用工具和脚本来自动生成 Changel…

STM32之USART_串口通讯

目录 引言 一、通讯相关基础 1.1 并行通讯与串行通讯 1.2 单工、半双工、全双工通讯 1.3 同步与异步通讯 1.4 串口介绍 1.5 串口通讯协议 二、USART外设 三、USART_功能框图原理介绍 四、波特率的设置 五、总结 引言 本次介绍STM32中片上外设中的模块之一——串口通…

平滑算法 效果比较

目录 高斯平滑 效果对比 移动平均效果比较: 高斯平滑 效果对比 右边两个参数是1.5 2 代码: smooth_demo.py import numpy as np import cv2 from scipy.ndimage import gaussian_filter1ddef gaussian_smooth_array(arr, sigma):smoothed_arr = gaussian_filter1d(arr, s…