springboot中规则引擎Drools的集成

1.场景还原

     近期笔者在架构新项目的过程中,对新项目的规则引擎单独拎出来作为一个模块;在面临规则需求可能多次变更的情况,后台全权控制规则引擎,更改规则配置后,不牵扯前端任何更改即可生效。

2.Drools规则引擎简介

  Drools是一款基于Java的开源规则引擎,实现了将业务决策从应用程序中抽离出来

  优点:

   ①简化系统架构哦,优化应用

   ②提高系统的可维护性和维护成本

   ③方便系统的整合

   ④减少编写“硬代码”业务规则的成本和风险

3.实现方案

①pom依赖

<!--规则引擎jboss rules相关的依赖-->
<dependency>
   <groupId>org.drools</groupId>
   <artifactId>drools-core</artifactId>
   <version>7.0.0.Final</version>
</dependency>
<dependency>
   <groupId>org.drools</groupId>
   <artifactId>drools-compiler</artifactId>
   <version>7.0.0.Final</version>
</dependency>
<dependency>
   <groupId>org.drools</groupId>
   <artifactId>drools-decisiontables</artifactId>
   <version>7.0.0.Final</version>
</dependency>
<dependency>
   <groupId>org.drools</groupId>
   <artifactId>drools-templates</artifactId>
   <version>7.0.0.Final</version>
</dependency>

<dependency>
   <groupId>org.kie</groupId>
   <artifactId>kie-api</artifactId>
   <version>7.0.0.Final</version>
</dependency>

<dependency>
   <groupId>org.mvel</groupId>
   <artifactId>mvel2</artifactId>
   <version>2.4.0.Final</version>
</dependency>

②规则配置

 1.在resources下新建META-INF目录,新建kmodule.xml配置类

<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <!--起步价-->
    <kbase name="baseprice" packages="rules.baseofprice">
        <ksession name="ksession-baseprice"/>
    </kbase>
</kmodule>

注意:这里的package指的是下文drl文件所在的包名,然后ksession-baseprice是规则service中必须引用的配置名

2.在resources下新建rules目录,新建以.drl结尾的规则引擎配置类

package com.yivi.yivisender;

import com.yivi.yivisender.dispatchcalengine.model.BasePrice;


//1阶梯
rule base_price_1
    salience 100
when
    $BasePrice : BasePrice(weight > basePriceConf.getFirstLadderKg() && weight <= basePriceConf.getSecondLadderKg())
then
    $BasePrice.setBaseOfValue($BasePrice.getBasePriceConf().getBaseFootPrice() * $BasePrice.getBasePriceConf().getFirstBaseTimes());
end

//2阶梯
rule base_price_2
    salience 99
when
    $BasePrice : BasePrice(weight > basePriceConf.getSecondLadderKg() && weight <= basePriceConf.getThirdLadderKg())
then
    $BasePrice.setBaseOfValue($BasePrice.getBasePriceConf().getBaseFootPrice() * $BasePrice.getBasePriceConf().getSecondBaseTimes());
end

//3阶梯
rule base_price_3
    salience 98
when
    $BasePrice : BasePrice(weight > basePriceConf.getThirdLadderKg() && weight <= basePriceConf.getForthLadderKg())
then
    $BasePrice.setBaseOfValue($BasePrice.getBasePriceConf().getBaseFootPrice() * $BasePrice.getBasePriceConf().getThirdBaseTimes());
end

//3阶梯
rule base_price_4
    salience 97
when
    $BasePrice : BasePrice(weight > basePriceConf.getForthLadderKg())
then
    $BasePrice.setBaseOfValue($BasePrice.getBasePriceConf().getBaseFootPrice() * $BasePrice.getBasePriceConf().getForthBaseTimes());
end

drools语法跟java很类似,上手很快,有兴趣的同学可以自己去研究下,笔者就此一笔带过;

③pom中build标签下resources配置,让系统识别drl配置

<resources>
   <resource>
      <directory>src/main/resources</directory>
      <includes>
         <include>**/*.properties</include>
         <include>**/*.xml</include>
         <include>**/*.yml</include>
         <include>**/*.drl</include>
      </includes>
      <filtering>false</filtering>
   </resource>
   <resource>
      <directory>src/main/java</directory>
      <includes>
         <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
   </resource>
</resources>

④规则实现类service

/**
 * @auther zx
 * @date 2018/7/9 16:58
 */
@Service
@Slf4j
public class BasePriceService {

    private static KieSession KIE_SESSION;

    @Autowired
    private DistributeConfService distributeConfService;

    static {
        KieServices ks = KieServices.Factory.get();
        KieContainer kContainer = ks.getKieClasspathContainer();
        KIE_SESSION = kContainer.newKieSession("ksession-baseprice");
    }

    public Double getBaseOfPrice(BasePrice basePrice) {
        initBasePriceConf(basePrice);
        KIE_SESSION.insert(basePrice);//插入
        KIE_SESSION.fireAllRules();//执行规则
        return basePrice.getBaseOfValue();

    }

    //初始化起步价配置
    private void initBasePriceConf(BasePrice basePrice){
        YiViDispatchBasePrice yiViDispatchBasePrice = null;
        if(basePrice.getCityCode() != null && !basePrice.getCityCode().equals("")){
            yiViDispatchBasePrice  = distributeConfService.getBasePriceConf(basePrice.getCityCode(),basePrice.getIsPin());
        }else{
            yiViDispatchBasePrice  = distributeConfService.getBasePriceConf("0",basePrice.getIsPin());
        }

        basePrice.setBasePriceConf(yiViDispatchBasePrice);
    }
}

4.测试用例

@Test
public void testBasePrice() {
   BasePrice basePrice = new BasePrice();
   basePrice.setWeight(51);
   basePrice.setIsPin(1);
   basePrice.setCityCode("0");
   Double price = basePriceService.getBaseOfPrice(basePrice);
   log.info("==================起步价测试:"+price);
}

运行结果:


好了,我是张星,欢迎加入博主技术交流群,群号:526601468

猜你喜欢

转载自blog.csdn.net/zhangxing52077/article/details/81025702