Drools是一款基于Java的优秀的规则引擎,将复杂多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得修改规则不需要改动代码重启服务就能生效。
Drools有一定的学习成本,官方英文文档非常详细,但中文文档少,本文将通过一篇文章来介绍Drools的使用和动态部署,这也是我学习过后的总结,希望对你入门Drools有帮助。
github: https://github.com/kiegroup/drools
简单使用
一个给不同商品设置不同折扣的例子
pom.xml
<dependency> <groupId>org.drools</groupId> <artifactId>drools-compiler</artifactId> <version>7.23.0.Final</version> </dependency>
kmodule.xml
文件用于配置规则脚本,可以有多个kbase
文件放在项目resources/META-INF
目录下可以自动加载
<?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://www.drools.org/xsd/kmodule"> <kbase name="rules" packages="rules"> <ksession name="ksession-rule"/> </kbase> </kmodule>
Product Bean实体
//lombok注解 @Data public class Product { public static final String DIAMOND = "DIAMOND"; public static final String GOLD = "GOLD"; private String type; private int discount; }
resources/rules/Rules.drl
规则脚本
package rules import drools.Product //当商品类型是DIAMOND时,打折为15% rule Offer4Diamond when productObject:Product(type == Product.DIAMOND) then productObject.setDiscount(15); end //当商品类型是GOLD时,打折为25% rule Offer4Gold when productObject: Product(type == Product.GOLD) then productObject.setDiscount(25); end
junit Test
@Test public void droolsTest() { KieServices ks = KieServices.Factory.get(); KieContainer kieContainer = ks.getKieClasspathContainer(); KieSession kSession = kieContainer.newKieSession("ksession-rule"); Product product = new Product(); product.setType(Product.GOLD); kSession.insert(product); int count = kSession.fireAllRules(); System.out.println("命中了" + count + "条规则"); System.out.println("商品" + product.getType() + "的商品折扣为" + product.getDiscount() + "%"); }
运行结果
命中了1条规则 商品GOLD的商品折扣为25%
解释一下
kmodule.xml
- 该文件用来配置规则表,可以包含多个kbase,每个kbase都有name属性,不能重复
- kbase可以包含多个ksession, packages属性是src/main/resources目录下文件夹的包路径,可以定义多个包,逗号分隔,packages目录下的所有规则文件都会被加载,除了子目录
- ksession 的name不能重复,Java代码中KieSession设置的name就是该配置的name
droolsTest
- KieServices
该接口提供了很多方法,可以通过这些方法访问KIE关于构建和运行的相关对象,比如说可以获取KieContainer,利用KieContainer来访问KBase和KSession等信息;可以获取KieRepository对象,利用KieRepository来管理KieModule等。
KieServices就是一个中心,通过它来获取的各种对象来完成规则构建、管理和执行等操作。 - KieContainer
KieContainer可以理解为是一个KieBase的容器。 - KieBase
KieBase可以理解为是一个知识仓库,包含了若干的规则、流程、方法等,在Drools中主要就是规则和方法,KieBase本身并不包含运行时的数据之类的,如果需要执行规则KieBase中的规则的话,就需要根据KieBase创建KieSession。 - KieSession
KieSession就是一个跟Drools引擎打交道的会话,其基于KieBase创建,它会包含运行时数据,包含“事实 Fact”,并对运行时数据事实进行规则运算。我们通过KieContainer创建KieSession是一种较为方便的做法,其实他本质上是从KieBase中创建出来
动态规则
实现动态规则有这几种思路
1. 使用Workbench,通过Web管理页面动态生成配置规则
2. 将规则以字符串的形式存入数据库,需要自己开发一套规则管理系统
使用Wrokbench
1.docker部署workbench
workbench
docker run -p 8080:8080 -p 8001:8001 -d --name drools-wb jboss/drools-workbench-showcase:7.5.0.Final
kie-server
docker run -p 8180:8180 -d --name kie-server --link drools-wb:kie_wb jboss/kie-server-showcase:7.5.0.Final
访问http://ip地址:8080/drools-wb
默认账号/密码 admin/admin
2.创建项目
3.创建Object
4.创建DRL文件
5.部署
6.使用部署的规则文件
远程规则Maven仓库地址获取
本地Maven仓库settings.xml配置,这里只摘录了需要添加的3处,需要对应去添加
<server> <username>admin</username> <password>admin</password> <id>guvnor-m2-repo</id> </server> <profile> <id>guvnor-m2-repo</id> <repositories> <repository> <id>guvnor-m2-repo</id> <name>Guvnor M2 Repo</name> <url>http://10.211.55.7:8080/drools-wb/maven2/</url> <layout>default</layout> <releases> <enabled>true</enabled> <updatePolicy>always</updatePolicy> </releases> <snapshots> <enabled>true</enabled> <updatePolicy>always</updatePolicy> <!--更新策略,常常 --> </snapshots> </repository> </repositories> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <activeProfiles> <activeProfile>guvnor-m2-repo</activeProfile> </activeProfiles>
创建一个标准的SpringBoot工程
Product
实体,包路径要跟规则文件中的一致
@Data public class Product { private String type; private int discount; }
DroolsController.java
@RestController @RequestMapping("/api/") @Slf4j public class DroolsController { @PostMapping("getdiscount") public Product getDiscount(Product product) throws IOException { KieServices ks = KieServices.Factory.get(); //RELEASE 代表使用jar包的最新正式版 ReleaseIdImpl releaseId = new ReleaseIdImpl("com.myteam", "test", "RELEASE"); KieContainer kieContainer = ks.newKieContainer(releaseId); //自动扫描Maven仓库,有新版本会自动下载 KieScanner kieScanner = ks.newKieScanner(kieContainer); kieScanner.start(3000); KieSession kieSession = kieContainer.newKieSession(); kieSession.insert(product); int count = kieSession.fireAllRules(); log.info("共执行了{}条规则", count); log.info("商品{}的折扣为{}%", product.getType(), product.getDiscount()); return product; } }
PostMan访问接口
与DRL规则文件中配置的一致
7.动态规则
修改ppdrl.drl
规则表,修改GOLD的打折为50%,保存规则,将项目版本提高一个版本,并build&deploy
项目
再次访问接口,GOLD的折扣已经变为50%
,其中没有重启服务