规则详解
@2016/11/4
一个规则通常包括三个部分:
- 属性部分(attribute)
- 条件部分(LHS)
- 结果部分(RHS)
LHS
- 当LHS为空时,引擎会自动添加一个eval(true)的条件,所以LHS为空的规则总是返回true。
- LHS部分事由一个或者多个条件组成,条件又称为pattern(匹配模式),多个pattern之间用and和or来进行连接,同时还可以使用括号赖确定pattern的优先级。
[绑定变量名:]Object([field约束])。绑定变量名是一个可选的别名,也可以用于对象的属性。field约束是指当前对象里相关字段的条件限制。field例子,下例中有俩个pattern,分别有三个约束,pattern之间没有连接词,引擎默认为and连接。
$customer:Customer(age>20,gender==’male’)
Order(customer==$customer,price>1000)- 约束连接,对于对象内部的多个约束的连接,可以采用“&&”
(and)、“||”(or)和“,”(and)来实现。这三个连接符号如果没有用小括号来显示的定义优先级的话,那么它们的执行顺序是:“&&”(and)、“||”(or)和“,”
RHS
- 在 RHS 当中可以使用 LHS 部分当中定义的绑定变量名(仅能使用当前LHS内定义的绑定变量名,即绑定变量名为规则内的局部变量)、设置的全局变量、或者是直接编写 Java 代码(对于要用到的 Java类,需要在规则文件当中用 import 将类导入后才能使用)
- insert(new Object());将一个 Fact 对象插入到当前的 Working Memory,注意一旦调用 insert 宏函数,那么 Drools 会重新与所有的规则再重新匹配一次,对于没有设置 no-loop 属性为 true 的规则,如果条件满足,不管其之前是否执行过都会再执行一次
- update(new Object());直接更新一个Fact对象,同上会重新执行一次所有的规则。
- retract($fact);删除一个Fact对象,同上
Drools宏对象的常用方法:
–getWorkingMemory() 获取当前的WorkingMemory对象
–alt()在当前规则执行完成后,不再执行其它未执行的规则
–getRule() 得到当前的规则对象
kcontext宏对象,得到当前的KnowledgeRuntime对象
- modify 是一个表达式块,可以实现对Fact对象多个属性进行修改,修改完后会自动更新到当前Working Memory当中。系统中必将用上,所以给出例子
package test
import java.util.List;
rule "rule1"
salience 2
when
$customer:Customer(name=="张三",age==20);
then
System.out.println("modify before customer
id:"+$customer.getId()+";age:"+$customer.getAge());
modify($customer){
setId("super man"),
setAge(30)
}
end
rule "rule2"
salience 1
when
$customer:Customer(name=="张三");
then
System.out.println("modify after customer id:"+$customer.getId()+";age:"+$customer.getAge());
end
attribute
- salience,在modify的例子中出现了,用于确定规则优先级,数字越大优先级越高。
- no-loop,是否可以多次执行,在目前的业务中一般设为true.
- date-effective,date-expires.由于目前的业务规则中不涉及规则控制,所以略过不提。
- enabled,定义一个规则是否可用。当值为false时引擎将不会执行该规则
- dialect,设置语言类型,选项为mval和java。默认java。
duration,比较有意思,可以开一个新的线程,对于duration的解释这里直接引用书上的内容
对于一个规则来说,如果设置了该属性,那么规则将在该属性指定的值之后在另外一个 线程里触发。该属性对应的值为一个长整型,单位是毫秒
lock-on-active,规则流相关,no-loop的增强版。
- activation-group,将若干个规则划分成一个组,用一个字符串来给这个组命名,这样在执行的时候,具有相同 activation-group 属性的规则中只要有一个会被执行,其它的规则都将不再执行。可以看作规则的互斥并行结构?
- agenda-group,auto-focus,ruleflow-group,没看懂
查询
无参数查询
query "testQuery"
customer:Customer(age>30,orders.size >10)
end
参数查询
query "testQuery"(int $age,String $gender)
customer:Customer(age>$age,gender==$gender)
end
调用查询
public class Test {
public static void main(String[] args) {
KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder();
kb.add(new ClassPathResource("test/test.drl"), ResourceType.DRL);
KnowledgeBase knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase();
knowledgeBase.addKnowledgePackages(kb.getKnowledgePackages());
StatefulKnowledgeSession statefulSession = knowledgeBase.newStatefulKnowledgeSession();
//向当前WorkingMemory当中插入Customer对象
statefulSession.insert(generateCustomer("张三",20,"F"));
statefulSession.insert(generateCustomer("李四",33,"M"));
statefulSession.insert(generateCustomer("王二",43,"F"));
//调用查询
QueryResults queryResults=statefulSession.getQueryResults("testQuery", new Object[]{new Integer(20),"F"});
for(QueryResultsRow qr:queryResults){
Customer cus=(Customer)qr.get("customer");
//打印查询结果
System.out.println("customer name :"+cus.getName());
}
statefulSession.dispose();
}
/**
* 产生Customer对象
* */
public static Customer generateCustomer(String name,int age,String gender){
Customer cus=new Customer();
cus.setAge(age);
cus.setName(name);
cus.setGender(gender);
return cus;
}
}
Fact对象
切记:
Fact 对象就是普通的具有若干个属性及其对应的 getter 与 setter方法的 JavaBean 对象
Drools 除了可以接受用户在外部向 WorkingMemory 当中插入现成的Fact 对象,还允许用户在规则文件当中定义一个新的 Fact 对象,目前用不上,故省略。
Domain Specific Language
可能以后会用上吧。。。