提示:本篇文章内容及案例来源于尚硅谷课程。详细源码可查看尚硅谷课程-乐尚代驾


前言

提示:这里可以添加本文要记录的大概内容:

需求:某电商平台的促销活动,活动规则是根据⽤户购买订单的⾦额给⽤户送相应的积分,购买的越多送的积分越多用户购买的金额和对应送多少积分的规则如下:

规则编号 订单金额 奖励积分
1 100元以下 不加积分
2 100元 - 500元 加100积分
3 500元 - 1000元 加500积分
4 1000元以上 加1000积分

思考:如何实现上面的业务需求?

使用基本分支判断(if - else)来实现,例如:

/**
 * 设置订单积分
 */
public void setOrderPoint(Order order){
    if (order.getAmount() <= 100){
        order.setScore(0);
    }else if(order.getAmount() > 100 && order.getAmount() <= 500){
        order.setScore(100);
    }else if(order.getAmount() > 500 && order.getAmount() <= 1000){
        order.setScore(500);
    }else{
        order.setScore(1000);
    }
}

通过上面的伪代码我们可以看到,需要在代码中写很多这样if else的代码。这种实现方式存在如下问题:

1、硬编码实现业务规则难以维护

2、硬编码实现业务规则难以应对变化

3、业务规则发生变化需要修改代码,重启服务后才能生效

那么面对上面的业务场景,还有什么好的实现方式吗?

此时我们需要引入规则引擎来帮助我们将规则从代码中分离出去,让开发人员从规则的代码逻辑中解放出来,把规则的维护和设置交由业务人员去管理。


一、规则引擎概述

(一)什么是规则引擎

规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。

需要注意的是规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。

规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。

系统中引入规则引擎后,业务规则不再以程序代码的形式驻留在系统中,取而代之的是处理规则的规则引擎,业务规则存储在规则库中,完全独立于程序。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。业务规则被加载到规则引擎中供应用系统调用。

(二)使用规则引擎的优势

使用规则引擎的优势如下:

1、业务规则与系统代码分离,实现业务规则的集中管理

2、在不重启服务的情况下可随时对业务规则进行扩展和维护

3、可以动态修改业务规则,从而快速响应需求变更

4、规则引擎是相对独立的,只关心业务规则,使得业务分析人员也可以参与编辑、维护系统的业务规则

5、减少了硬编码业务规则的成本和风险

6、使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单

(三)规则引擎应用场景

对于一些存在比较复杂的业务规则并且业务规则会频繁变动的系统比较适合使用规则引擎,如下:

1、风险控制系统----风险贷款、风险评估

2、反欺诈项目----银行贷款、征信验证

3、决策平台系统----财务计算

4、促销平台系统----满减、打折、加价购

(四)Drools介绍

drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。

二、Drools入门案例

(一)创建SpringBoot项目

项目依赖(示例):

 <parent>
  <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-parent</artifactId>
     <version>3.0.5</version>
     <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
     <java.version>17</java.version>
     <drools.version>8.41.0.Final</drools.version>
 </properties>

 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>

     <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-core</artifactId>
         <version>${drools.version}</version>
     </dependency>
     <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-compiler</artifactId>
         <version>${drools.version}</version>
     </dependency>
     <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-decisiontables</artifactId>
         <version>${drools.version}</version>
     </dependency>
     <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-mvel</artifactId>
         <version>${drools.version}</version>
     </dependency>
 </dependencies>

(二)添加Drools配置类

代码如下(示例):

import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DroolsConfig {

    private static final KieServices kieServices = KieServices.Factory.get();
    //制定规则文件的路径
    private static final String RULES_CUSTOMER_RULES_DRL = "rules/order.drl";

    @Bean
    public KieContainer kieContainer() {
        //获得Kie容器对象
        KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
        kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));

        KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
        kieBuilder.buildAll();

        KieModule kieModule = kieBuilder.getKieModule();
        KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());

        return kieContainer;
    }
}

说明:

  • 定义了一个 KieContainerSpring BeanKieContainer用于通过加载应用程序的/resources文件夹下的规则文件来构建规则引擎。
  • 创建KieFileSystem实例并配置规则引擎并从应用程序的资源目录加载规则的 DRL 文件。
  • 使用KieBuilder实例来构建 drools 模块。我们可以使用KieSerive单例实例来创建 KieBuilder 实例。
  • 最后,使用 KieService 创建一个 KieContainer 并将其配置为 spring bean

(三)创建实体类Order

public class Order {

    private double amount;
    private double score;

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

(四)添加order.drl

创建规则文件resources/rules/order.drl

//订单积分规则
package com.order
import com.example.demo.entity.Order

//规则一:100元以下 不加分
rule "order_rule_1"
    when
        $order:Order(amount < 100)
    then
        $order.setScore(0);
        System.out.println("成功匹配到规则一:100元以下 不加分");
end

//规则二:100元 - 500元 加100分
rule "order_rule_2"
    when
        $order:Order(amount >= 100 && amount < 500)
    then
         $order.setScore(100);
         System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end

//规则三:500元 - 1000元 加500分
rule "order_rule_3"
    when
        $order:Order(amount >= 500 && amount < 1000)
    then
         $order.setScore(500);
         System.out.println("成功匹配到规则三:500元 - 1000元 加500分");
end

//规则四:1000元以上 加1000分
rule "order_rule_4"
    when
        $order:Order(amount >= 1000)
    then
         $order.setScore(1000);
         System.out.println("成功匹配到规则四:1000元以上 加1000分");
end

(五)编写测试类

@Test
public void test(){
      //从Kie容器对象中获取会话对象
      KieSession session = kieContainer.newKieSession();

      //Fact对象,事实对象
      Order order = new Order();
      order.setAmount(1300);

      //将Order对象插入到工作内存中
      session.insert(order);

      //激活规则,由Drools框架自动进行规则匹配,如果规则匹配成功,则执行当前规则
      session.fireAllRules();
      //关闭会话
      session.dispose();

      System.out.println("订单金额:" + order.getAmount() +
              ",添加积分:" + order.getScore());
  }
输出结果:
成功匹配到规则四:1000元以上 加1000分
订单金额:1300.0,添加积分:1000.0

(六)项目结构

在这里插入图片描述


总结

以上只是一个简单的案例,如何使用 Drools 规则引擎将业务决策从应用程序代码中分离出来,防止硬编码,让整个系统更加灵活。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐