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