贴个Drools 7.15.0官方文档地址:https://docs.jboss.org/drools/release/7.15.0.Final/drools-docs/html_single/index.html
这个链接可以下载PDF版本的文档:http://www.drools.org/learn/documentation.html
规则引擎在IoT的数据过滤,保险业务系统,积分系统等很多场景都应用广泛。使用规则引擎最大的好处是可以将规则与业务代码分离,动态增加和删除规则,可以做到很友好的提供给业务操作人员去编辑具体的业务规则,而非技术开发人员。drools作为开源项目中比较知名的规则引擎之一,想必会有很多人想使用它来应对逐渐复杂的业务规则。下面我们介绍怎样通过drools实现动态的规则管理。
首先在自己工程中引入drools依赖包,pom.xml如下配置:
org.drools
drools-core
7.2.0.Final
org.drools
drools-compiler
7.2.0.Final
org.kie
kie-api
7.2.0.Final
org.kie
kie-internal
7.2.0.Final
接下来,引用官方示例,直接上代码,
String rule = "import com.demo.drools.Cheese;\r\n" +
"import com.demo.drools.Person;\r\n" +
"rule \"规则\"\r\n"+
"when\r\n" +
" Cheese( $cheese : name == \"cheddar\" )\r\n"+
" $person : Person( favouriteCheese == $cheese )\r\n" +
"then\r\n"+
" System.out.println( $person.getName() + \" likes cheddar\" );\r\n" + "end\r\n" + " ";
KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
//以DRL形式加载规则
builder.add(ResourceFactory.newByteArrayResource(rule.getBytes()), ResourceType.DRL);
KnowledgeBuilderErrors errors = builder.getErrors();
for (KnowledgeBuilderError error : errors) {
System.out.println(error.getMessage());
}
InternalKnowledgeBase kBase = KnowledgeBaseFactory.newKnowledgeBase();
kBase.addPackages(builder.getKnowledgePackages());
//获取规则引擎会话session
KieSession session = kBase.newKieSession();
Person person1 = new Person("张三", "cheddar");
Person person2 = new Person("李四", "dicars");
Cheese cheese1 = new Cheese("cheddar");
Cheese cheese2 = new Cheese("dicars");
//插入需匹配的对象
session.insert(person1);
session.insert(person2);
session.insert(cheese1);
session.insert(cheese2);
//执行规则
session.fireAllRules();
//释放资源
session.dispose();
public class Person {
private String favouriteCheese;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(String name, String favourite) {
favouriteCheese = favourite;
this.name = name;
}
public String getFavouriteCheese() {
return favouriteCheese;
}
public void setFavouriteCheese(String favouriteCheese) {
this.favouriteCheese = favouriteCheese;
}
}
/*****************************************************************/
public class Cheese {
private String name;
public Cheese(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
示例中的规则是以DRL文件形式加载的,所以我们可以自己生成合法的DRL文本,然后初始化规则引擎实例。Drools支持多种不同的规则表达形式,例如决策表,properties文件,DSL语言,java语言,XML等十几种形式,同时支持多种规则加载方式,例如字节流,文件,I/O流,URL,String等。所以,想实现动态加载规则的方法有很多,感兴趣的话可以自己去尝试其他的方法。初始化规则引擎之后,内部会按照Rete算法生成匹配网络,然后我们就可以向里面insert需要匹配的对象,添加完对象后,显示调用session.fireAllRules()方法让规则引擎工作,最后符合条件的对象会执行规则的动作。
官方推荐使用DSL(Domain Specified Language)领域专用语言书写规则,领域专家可以通过简单的编程方式描述领域中的所有活动和规则。下面介绍上面例子中用DSL语言书写的规则:
rule "规则"
when
Cheese( $cheese : name == "cheddar" )
$person : Person( favouriteCheese == $cheese )
then
System.out.println( $person.getName() + " likes cheddar" );
end
上面这条规则表示:“最喜欢奶酪品牌是'cheddar'的人的姓名有哪些”。这条规则包含了条件(when)和动作(then),条件是用DSL语言书写,动作可以用java语言书写。规则实际上包含了3个条件,分别是
只有满足以上条件的对象才能被执行动作(then)部分。DSL语言中还有非常多的关键字可以使用,比如循环的执行规则,定时执行规则等等操作,下面这个链接详细的解释了DSL可以使用的一些关键字和函数,可以很方便的完成一些操作。
https://docs.jboss.org/drools/release/7.15.0.Final/drools-docs/html_single/index.html#_droolslanguagereferencechapter
上面实现了动态加载规则,并且成功执行结果,那么接下来我们可以让规则的编写简单化。对于业务人员来说,最好的方式是使用自然语言书写规则。那么我们需要做的就是把自然语言编写的规则转换为DSL语言。仍然以上面的规则为例,“最喜欢奶酪品牌是'cheddar'的人的姓名有哪些”。业务人员只需要输入:
条件:人.喜欢的奶酪名='cheddar'
动作:输出->人.姓名
我们将这句话一一转换为DSL对应的语言。首先是对象的转换:人->Person,奶酪->Cheese;属性的转换:奶酪名->Cheese.name,姓名->Person.name,喜欢的奶酪名->Person.favouriteCheese ;动作的转换:输出->System.out.println();逻辑运算符的转换:"="->"==",对象的引用约定为:$对象名,因此人和奶酪的对象引用转换为:$person,$cheese;'('、')'和""引号、括号等符号作为语义补充,所以得到转换后的部分DSL为:
//条件语句
Cheese( $cheese : name == "cheddar" )
$person : Person( favouriteCheese == $cheese )
//动作语句
System.out.println( $person.getName() + " likes cheddar" )
再将上面的代码片段组合成标准的DSL格式:
rule "规则"
when
//条件语句
Cheese( $cheese : name == "cheddar" )
$person : Person( favouriteCheese == $cheese )
then
//动作语句
System.out.println( $person.getName() + " likes cheddar" )
end
那么一个简单的自然语言的规则就转换为一个标准的DSL语句。当然更复杂的语句也基本类似,无非是对更多的运算符,关键字等分别做转换。对语言的处理继续深入的话其实非常的丰富和具有挑战性。
后续我会继续分享怎样将SQL语句转换为DSL语言。SQL作为模式匹配语言中的一种,在条件过滤和数据筛选方面非常灵活,那么后面我们将分享怎样让SQL语句运行在Drools规则引擎之上。