规则引擎Drools
Drools(JBoss Rules )具有一个易于访问企业策略、易于调整以及易于管理的开源业务规则引擎。Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效。项目中公司计算工资的系统使用的就是规则引擎,计算不同岗位的工资。
规则脚本有自己的语法规则,这篇博客主要介绍学习过程中的心得体会和一些需要记录的地方,加深印象,学习的是Drools5的语法,Drools最新版本已经到6.5了。eclipse有规则引擎的相关插件,用来编写规则文件,引入规则引擎开发工具包。有了开发工具包才可以正常使用规则引擎。
第一个测试
public class Test{
public static void main(String[] args){
KnowledgeBuilder kbuilder=KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("test.drl", Test.class),ResourceType.DRL);//引入类路径下的test.drl规则文件
Collection<KnowledgePackage> kpackage=kbuilder.getKnowledgePackages();//产生规则包的集合
KnowledgeBase kbase=KnowledgeBaseFactory.newKnowledgeBase();
//上面默认配置or下面自定义配置
KnowledgeBaseConfiguration kbConf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
kbConf.setProperty( "org.drools.sequential", "true");
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(kbConf);
kbase.addKnowledgePackages(kpackage);//将knowledgePackage集合添加到knowledgeBase中。
StatefulKnowledgeSession statefulKSession=kbase.newStatefulKnowledgeSession();
statefulKSession.setGlobal("globalTest", new Customer());//设置一个global对象
Customer cus = new Customer();
cus.setName("张三");
statefulKSession.insert(cus);//插入一个fact对象
statefulKSession.fireAllRules();//触发所有的规则执行
statefulKSession.dispose();//释放内存资源
}
}
KnowledgeBuilder 的作用就是用来在业务代码当中收集已经编写好的规则,然后对这些规则文件进行编译,最终产生一批编译好的规则包(KnowledgePackage)给其它的应用程序使用。
KnowledgeBase知识库对象,给规则引擎定义环境变量,更多环境变量参考官网
StatefulKnowledgeSession用于使编译好的规则包文件在规则引擎当中运行起来。
Fact是指在Drools规则应用当中,将一个普通的JavaBean插入到规则的WorkingMemory当中后的对象
规则文件
以“.drl”结尾的文本文件。
一个标准规则文件的结构:
package //类似java的包,这里用于区别规则
imports //引入类、方法等
globals //全局变量
functions //定义函数
queries //定义查询
rules //规则主体
一个可能的规则文件
package com.lancy.drools.test
import java.util.List
rule "rule1"
salience 2
when
eval(true)
then
Customer customer = new Customer();
customer.setName("张三");
insert(customer);
end
rule "rule2"
salience 1
when
$customer:Customer(name == "张三")
then
System.out.println("rule2----" + $customer.getName())
end
规则语言
一个规则通常包括三个部分:属性部分(attribute)、条件部分(LHS)和结果部分(RHS)。其中条件部分写判断语句,如比较操作符。判断为true,则执行结果部分,如增删改查。具体的语法参考后面的文档
规则属性
规则的属性有10多个:
salience
设置规则执行的优先级。在一个规则文件中可能有多个rule。设置salience可以设置规则执行的优先级,数字越大优先级越高salience 5
no-loop
no-loop 属性的作用是用来控制已经执行过的规则在条件再次满足时是否再次执行。默认情况下规则的 no-loop属性的值为 false,如果 no-loop 属性值为 true,那么就表示该规则只会被引擎检查一次。当执行RHS中,增删改执行后,Drools会重新与所有的规则再重新匹配一次,对于没有设置no-loop为true的规则,不管之前是否执行过,如果条件为真,都会重新再执行一次RHS。
还有其他的属性参考文档。
函数
函数是定义在规则文件当中一代码块,作用是将在规则文件当中若干个规则都会用到的业务操作封装起来,实现业务代码的复用,减少规则编写的工作量。
函数的编写位置可以是规则文件当中 package 声明后的任何地方。语法是标准的java语法
function void/Object functionName(Type arg...) {
/*函数体的业务代码*/
}
function void printName(String name){
System.out.println("name is " + name);
}
查询
规则文件:
query "testQuery1"
customer:Customer(age>30)
end
//or
query "testQuery2"(int $age, String $name)
customer:Customer(age>$age,name == $name)
end
测试代码:
StatefulKnowledgeSession statefulSession=kbase.newStatefulKnowledgeSession();
statefulSession.insert(new Customer("张三",35));
statefulSession.insert(new Customer("李四",25));
statefulSession.insert(new Customer("王五",33));
QueryResults queryResults = statefulSession.getQueryResults("testQuery");
for(QueryResultsRow qr:queryResults){
Customer cus=(Customer)qr.get("customer");
//打印查询结果
System.out.println("customer name :"+cus.getName());
}
statefulSession.dispose();
//or
StatefulKnowledgeSession statefulSession=kbase.newStatefulKnowledgeSession();
statefulSession.insert(new Customer("张三",35));
statefulSession.insert(new Customer("李四",25));
statefulSession.insert(new Customer("王五",33));
QueryResults queryResults = statefulSession.getQueryResults("testQuery",new Object[]{new Integer(20),"张三"});
for(QueryResultsRow qr:queryResults){
Customer cus=(Customer)qr.get("customer");
//打印查询结果
System.out.println("customer name :"+cus.getName());
}
statefulSession.dispose();
就记录这么多。更多的知识参考,有详细的介绍
[https://wenku.baidu.com/view/a6516373f242336c1eb95e7c.html?pn=51](https://wenku.baidu.com/view/a6516373f242336c1eb95e7c.html?pn=51)