因为在项目要用到Drools,所以下面写了一个简单的例子学习入门。
一、Drools简介:
JBoss Rules 的前身是Codehaus的一个开源项目叫 Drools。最近被纳入JBoss门下,更名为JBoss Rules,成为了JBoss应用服务器的规则引擎。
Drools 是为 Java 量身定制的基于Charles Forgy的RETE算法的规则引擎的实现。具有了OO接口的RETE,使得商业规则有了更自然的表达。
Drools 的用 XML 的<Conditons>、<Consequence> 节点表达If–Then句式,而里面可以嵌入上述语言的代码作为判断语句和执行语句。
其中 Java 代码会使用Antlr进行解释,而 Groovy 和 Python 本身就是脚本语言,可以直接调用。
Drools 的聪明之处在于,用 XML 节点来规范 If–Then 句式和事实的定义,使引擎干起活来很舒服。
而使用 Java,Groovy等原生语言来做判断和执行语句,让程序员很容易过渡、移植,学习曲线很低。
二、几个重要概念
- 事实(Fact):对象之间及对象属性之间的关系
- 规则(rule):是由条件和结论构成的推理语句,一般表示为if...Then。一个规则的if部分称为LHS,then部分称为RHS。
- 模式(module):就是指IF语句的条件。这里IF条件可能是有几个更小的条件组成的大条件。模式就是指的不能在继续分割下去的最小的原子条件。
三、.drl 文件内容
package com.rules
import com.drools.model.Person
import com.drools.model.Goods
rule "test-drools-older than 60"
when
no-loop true
lock-on-active true
salience 1
$Goods : Goods(person.age > 60)
then
$Goods.setDiscount(80);
System.out.println("test-drools-older than 60 " + $Goods.getPerson().getAge());
end
- package 与Java语言类似,drl的头部需要有package和import的声明,package不必和物理路径一致。
- import 导出java Bean的完整路径,也可以将Java静态方法导入调用。
- rule 规则名称,需要保持唯一 件,可以无限次执行。
- no-loop 定义当前的规则是否不允许多次循环执行,默认是 false,也就是当前的规则只要满足条件,可以无限次执行。
- lock-on-active 将lock-on-active属性的值设置为true,可避免因某些Fact对象被修改而使已经执行过的规则再次被激活执行。
- salience 用来设置规则执行的优先级,salience 属性的值是一个数字,数字越大执行优先级越高, 同时它的值可以是一个负数。默认情况下,规则的 salience 默认值为 0。如果不设置规则的 salience 属性,那么执行顺序是随机的。
- when 条件语句,就是当到达什么条件的时候
- then 根据条件的结果,来执行什么动作
- end 规则结束
这个规则文件就是描述了,当符合什么条件的时候,应该去做什么事情,每当规则有变动的时候,我们只需要修改规则文件,然后重新加载即可生效。
四、kmodule.xml
kmodule.xml的作用就是告诉代码规则文件drl在哪里,在drools中这个文件就是kmodule.xml,放置到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>
以下对配置说明进行简单说明:
- Kmodule 中可以包含一个到多个 kbase,分别对应 drl 的规则文件。
- Kbase 需要一个唯一的 name,可以取任意字符串。
- packages 为drl文件所在resource目录下的路径。注意区分drl文件中的package与此处的package不一定相同。多个包用逗号分隔。默认情况下会扫描 resources目录下所有(包含子目录)规则文件。
- kbase的default属性,标示当前KieBase是不是默认的,如果是默认的则不用名称
就可以查找到该 KieBase,但每个 module 最多只能有一个默认 KieBase。- kbase 下面可以有一个或多个 ksession,ksession 的 name 属性必须设置,且必须唯一。
五、下面是一个简单的入门例子
1、首先项目的结构如下
2、引入drools的依赖
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.7.0.Final</version>
</dependency>
</dependencies>
3、创建一个xml,注意一定要放在META-INF文件夹下,drools会自动解析它
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules">
<ksession name="all-rules"/>
</kbase>
</kmodule>
4、创建实体Goods和Person
5、创建规则droolsRules.drl
package com.rules
import com.drools.model.Person
import com.drools.model.Goods
rule "test-drools-older than 60"
when
$Goods : Goods(person.age > 60)
then
$Goods.setDiscount(80);
System.out.println("test-drools-older than 60 " + $Goods.getPerson().getAge());
end
rule "test-drools-other"
when
$Goods : Goods(person.age <= 60)
then
$Goods.setDiscount(70);
System.out.println("test-drools-other " + $Goods.getPerson().getAge());
end
6、测试类
public class DroolsTest {
public static void main(String[] args) {
//获取一个实例
KieServices kieServices = KieServices.Factory.get();
//默认去读取配置文件
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//根据这个名词去获取kieSession
KieSession kieSession = kieContainer.newKieSession("all-rules");
Person p1 = new Person();
p1.setAge(30);
p1.setName("Tom");
Goods g1 = new Goods();
g1.setPerson(p1);
Person p2 = new Person();
p2.setAge(70);
p2.setName("Joy");
Goods g2 = new Goods();
g2.setPerson(p2);
//将person实例放入session中
kieSession.insert(g1);
kieSession.insert(g2);
//开始执行规则,并获取执行了多少条规则
int count = kieSession.fireAllRules();
//关闭session
kieSession.dispose();
System.out.println("Fire " + count + " rule(s)!");
System.out.println("The discount of g1 is " + g1.getDiscount() + "%");
System.out.println("The discount of g2 is " + g2.getDiscount() + "%");
}
}
7、运行结果
test-drools-older than 60 70
test-drools-other 30
Fire 2 rule(s)!
The discount of g1 is 70%
The discount of g2 is 80%