1. Drools引擎简介 1、基础简介
Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效。具有易于访问企业策略、易于调整以及易于管理的特点,作为开源业务规则引擎,符合业内标准,速度快、效率高。
2、规则语法
(1)、演示drl文件格式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import com.xxyx.mvel.entity.OrderRequest;import com.xxyx.mvel.enums.CustomerType;global com.xxyx.mvel.entity.OrderDiscount orderDiscount; dialect "mvel" rule "Age based discount" when OrderRequest(age < 20 || age > 50 ) then System.out.println("==========Adding 10% discount for Kids/ senior customer=============" ); orderDiscount.setDiscount(orderDiscount.getDiscount() + 10 ); end rule "Customer type based discount - Loyal customer" when OrderRequest(customerType.getValue == "LOYAL" ) then System.out.println("==========Adding 5% discount for LOYAL customer=============" ); orderDiscount.setDiscount(orderDiscount.getDiscount() + 5 ); end rule "Customer type based discount - others" when OrderRequest (customerType.getValue != "LOYAL" ) then System.out.println("==========Adding 3% discount for NEW or DISSATISFIED customer=============" ); orderDiscount.setDiscount(orderDiscount.getDiscount() + 3 ); end rule "Amount based discount" when OrderRequest (amount > 1000 ) then System.out.println("==========Adding 5% discount for amount more than 1000$=============" ); orderDiscount.setDiscount(orderDiscount.getDiscount() + 5 ); end
(2)、语法说明
· 文件格式
可以 .drl、xml文件,也可以Java代码块硬编码;
· package
规则文件中,package是必须定义的,必须放在规则文件第一行;
· import
规则文件使用到的外部变量,可以是一个类,也可以是类中的可访问的静态方法;
· rule
定义一个规则。paramcheck1规则名。规则通常包含三个部分:属性、条件、结果;
二、整合SpringBoot框架
1、项目结构
SpringBoot2 整合 Drools规则引擎,实现高效的业务规则
2、核心依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!-- 规则引擎 3 个 --> <dependency> <groupId>org.drools</groupId> <artifactId>drools-core</artifactId> <version>7.74 .0 .Final</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.74 .0 .Final</version> </dependency> <dependency> <groupId>org.drools</groupId> <artifactId>drools-decisiontables</artifactId> <version>7.74 .0 .Final</version> </dependency> <!-- Mvel表达式 --> <dependency> <groupId>org.mvel</groupId> <artifactId>mvel2</artifactId> <version>2.4 .12 .Final</version> </dependency>
3、配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 package com.xxyx.mvel.config;import org.kie.api.KieBase;import org.kie.api.KieServices;import org.kie.api.builder.KieBuilder;import org.kie.api.builder.KieFileSystem;import org.kie.api.builder.KieRepository;import org.kie.api.runtime.KieContainer;import org.kie.internal.io.ResourceFactory;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.Resource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternResolver;import java.io.IOException;@Configuration public class DroolsAutoConfiguration { private static final String RULES_PATH = "rules/" ; private KieServices getKieServices () { return KieServices.Factory.get(); } @Bean @ConditionalOnMissingBean(KieFileSystem.class) public KieFileSystem kieFileSystem () throws IOException { KieFileSystem kieFileSystem = getKieServices().newKieFileSystem(); for (Resource file : getRuleFiles()) { kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + file.getFilename(), "UTF-8" )); } return kieFileSystem; } private Resource[] getRuleFiles() throws IOException { ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver (); return resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "**/*.*" ); } @Bean @ConditionalOnMissingBean(KieContainer.class) public KieContainer kieContainer () throws IOException { final KieRepository kieRepository = getKieServices().getRepository(); kieRepository.addKieModule(() -> kieRepository.getDefaultReleaseId()); KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem()); kieBuilder.buildAll(); KieContainer kieContainer = getKieServices().newKieContainer(kieRepository.getDefaultReleaseId()); return kieContainer; } @Bean @ConditionalOnMissingBean(KieBase.class) public KieBase kieBase () throws IOException { return kieContainer().getKieBase(); } }
这样环境整合就完成了。
1、规则调用接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import com.alibaba.fastjson2.JSON;import com.xxyx.mvel.MvelApplication;import com.xxyx.mvel.entity.OrderDiscount;import com.xxyx.mvel.entity.OrderRequest;import com.xxyx.mvel.enums.CustomerType;import com.xxyx.mvel.service.OrderDiscountService;import lombok.extern.slf4j.Slf4j;import org.junit.Test;import org.junit.jupiter.api.DisplayName;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@Slf4j @SpringBootTest(classes = MvelApplication.class) @RunWith(SpringRunner.class) public class MvelApplicationTest { @Autowired private OrderDiscountService orderDiscountService; @Test @DisplayName("drools表达式") public void droolsExpr () { OrderRequest orderRequest = new OrderRequest ("123456" ,19 , 20000 , CustomerType.LOYAL); OrderDiscount discount = orderDiscountService.getDiscount(orderRequest); System.out.println(JSON.toJSONString(discount)); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.xxyx.mvel.service;import com.xxyx.mvel.entity.OrderDiscount;import com.xxyx.mvel.entity.OrderRequest;import org.kie.api.runtime.KieContainer;import org.kie.api.runtime.KieSession;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Service public class OrderDiscountService { @Autowired private KieContainer kieContainer; public OrderDiscount getDiscount (OrderRequest orderRequest) { OrderDiscount orderDiscount = new OrderDiscount (); KieSession kieSession = kieContainer.newKieSession(); kieSession.setGlobal("orderDiscount" , orderDiscount); kieSession.insert(orderRequest); kieSession.fireAllRules(); kieSession.dispose(); return orderDiscount; } }
规则说明:
A、当客户年龄在20岁以下或者50岁以上,+10%;
B、当客户类型是LOYAL,+5%。
C、当客户类型不是LOYAL,+3%。
D、当订单金额 > 1000,+5%。
最终输出:
==========Adding 10% discount for Kids/ senior customer============= ==========Adding 5% discount for LOYAL customer============= ==========Adding 5% discount for amount more than 1000$============= {“discount”:20}