Drools简介
Drools是一款基于Java的开源规则引擎,将规则与业务代码解耦。规则以脚本的形式存储在一个文件中,使规则的变化不需要修改代码,重新启动机器即可在线上环境中生效。
规则引擎实现了业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入、解释业务规则,以及基于业务规则做出业务决策,从而提供极大的编程便利。
对系统使用人员来说:
- 将业务规则的创建、修改、维护透明话;
- 提高业务灵活度;
- 减少对开发人员的依赖;
- 避免业务升级带来的风险;
对开发人员来说:
- 增加代码灵活性;
- 降低系统维护成本,提高系统可维护性;
- 解耦业务与规则,减少代码修改成本;
- 简化系统架构,优化应用结构;
引入规则引擎前后程序架构:
引入前:
引入后:
idea 搭建 Drools 开发环境
-
安装Drools idea插件
idea界面一次选择:File => Settings => Plugins => 搜索Drools =>安装JBoss Drools support
-
引入依赖
导入Drools依赖时顺便导入SpringBoot Test的依赖,方便接下来的测试,除了上述两个依赖外还需要引入kie-api的依赖,因为Drools基于Kie概念的API,对之前版本繁琐的规则引擎调用方式进行了优化。
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.23.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.drools/drools-compiler -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.23.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.23.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.23.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.23.0.Final</version>
</dependency>
<!--springboot程序测试依赖,如果是自动创建项目默认添加-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
-
配置kmodule文件
在resources下创建META-INF文件夹,并且创建文件kmodule.xml,文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules">
<ksession name="all-rules"/>
</kbase>
</kmodule>
文件各项配置的作用会在接下来的文章中提及。
Drools简单示例(包括动态加载配置文件)
-
创建规则操作数据对象
package com.asiainfo.bean;
/**
* Title Person
* Package com.asiainfo.bean
* Description Person类
* Author 唐磊
* Date 2019-07-06 14:25
*/
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
-
创建规则文件drl
在resources下创建rules文件夹,并创建规则文件。
代码如下:
import com.asiainfo.bean.Person
dialect "mvel"
rule "age"
when
$person : Person(age<16 || age>50)
then
System.out.println("这个人的年龄不符合要求!(基于规则文件)");
end
规则文件具体语法会在接下来的文章中提及。
-
测试(基于规则文件的)
代码:
import com.asiainfo.Application;
import com.asiainfo.bean.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieServices;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Title TestDrools
* Package
* Description 测试Drools类
* Author 唐磊
* Date 2019-07-06 14:26
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
public class TestDrools {
private static KieContainer container = null;
private KieSession statefulKieSession = null;
/**
* Title test
* Param []
* Return void
* Exception
* Description 基于配置文件
* Author 唐磊
* Date 2019-07-06 14:27
*/
@Test
public void test() {
KieServices kieServices = KieServices.Factory.get();
container = kieServices.getKieClasspathContainer();
statefulKieSession = container.newKieSession("all-rules");
Person person = new Person();
person.setAge(12);
person.setName("Test");
statefulKieSession.insert(person);
statefulKieSession.fireAllRules();
statefulKieSession.dispose();
}
}
测试结果:
输出 这个人的年龄不符合要求!(基于规则文件)
4.
测试动态加载规则(基于字符串)
代码:
import com.asiainfo.Application;
import com.asiainfo.bean.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieServices;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.utils.KieHelper;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* Title TestDrools
* Package
* Description 测试Drools类
* Author 唐磊
* Date 2019-07-06 14:26
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
public class TestDrools {
private static KieContainer container = null;
private KieSession statefulKieSession = null;
/**
* Title ruleStringTest
* Param []
* Return void
* Exception
* Description 基于字符串
* Author 唐磊
* Date 2019-07-06 14:27
*/
@Test
public void ruleStringTest() throws Exception {
String myRule = "import com.asiainfo.bean.Person\n" +
"\n" +
"dialect \"mvel\"\n" +
"\n" +
"rule \"age\"\n" +
" when\n" +
" $person : Person(age<16 || age>50)\n" +
" then\n" +
" System.out.println(\"这个人的年龄不符合要求!(基于动态加载)\");\n" +
"end\n";
KieHelper helper = new KieHelper();
helper.addContent(myRule, ResourceType.DRL);
KieSession ksession = helper.build().newKieSession();
Person person = new Person();
person.setAge(12);
person.setName("Test");
ksession.insert(person);
ksession.fireAllRules();
ksession.dispose();
}
}
测试结果:
输出 这个人的年龄不符合要求!(基于动态加载)
上述测试说明Drools可以基于字符串配置规则,那么我们在开发时就可以将自己配置的规则存到数据库等存储介质中,实时调用动态加载配置规则。
PS:接下来我会进行动态加载规则的性能测试,然后进一步完善动态配置规则的方案。
版权声明:本文为tanglei6636原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。