自学内容网 自学内容网

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

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; // 规则ID
    private 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 {

    @Autowired
    private CouponService couponService;

    /**
     * 评估条件
     * @param facts 事实对象
     * @return 是否满足条件
     * @throws Exception 异常
     */
    @Override
    @Condition
    public boolean evaluate(Facts facts) throws Exception {
        returnsuper.evaluate(facts);
    }

    /**
     * 执行动作
     * @param facts 事实对象
     * @throws Exception 异常
     */
    @Override
    @Action
    public 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 规则引擎实例
     */
    @Bean
    public 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 {

    @Autowired
    private 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 {

    @Autowired
    private RulesEngine rulesEngine; // 规则引擎

    @Autowired
    private DynamicCouponRule dynamicCouponRule; // 动态规则

    @Autowired
    private CouponService couponService; // 优惠券服务

    public static void main(String[] args) {
        SpringApplication.run(CouponSystemApplication.class, args);
    }

    /**
     * 应用启动时运行的方法
     * @param args 命令行参数
     * @throws Exception 异常
     */
    @Override
    public 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}; // 数据库中的规则ID
        for (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


原文地址:https://blog.csdn.net/qq_18244417/article/details/145127953

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!