第2-4-3章 规则引擎Drools基础语法-业务规则管理系统-组件化-中台 ...

打印 上一主题 下一主题

主题 1866|帖子 1866|积分 5598

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
目录

4. Drools基础语法

全套代码及资料全部完整提供,点此处下载
4.1 规则文件构成

在使用Drools时非常重要的一个工作就是编写规则文件,通常规则文件的后缀为.drl。
drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。
一套完整的规则文件内容构成如下:
关键字描述package包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用import用于导入类或者静态方法global全局变量function自定义函数query查询rule end规则体Drools支持的规则文件,除了drl形式,还有Excel文件类型的。
4.2 规则体语法结构

规则体是规则文件内容中的重要组成部分,是进行业务规则判断、处理业务结果的部分。
规则体语法结构如下:
  1. rule "ruleName"
  2.     attributes
  3.     when
  4.         LHS
  5.     then
  6.         RHS
  7. end
复制代码
rule:关键字,表示规则开始,参数为规则的唯一名称。
attributes:规则属性,是rule与when之间的参数,为可选项。
when:关键字,后面跟规则的条件部分。
LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。
then:关键字,后面跟规则的结果部分。
RHS(Right Hand Side):是规则的后果或行动部分的通用名称。
end:关键字,表示一个规则结束。
4.3 注释

在drl形式的规则文件中使用注释和Java类中使用注释一致,分为单行注释和多行注释。
单行注释用"//"进行标记,多行注释以"/*"开始,以"*/"结束。如下示例:
  1. //规则rule1的注释,这是一个单行注释
  2. rule "rule1"
  3.     when
  4.     then
  5.             System.out.println("rule1触发");
  6. end
  7. /*
  8. 规则rule2的注释,
  9. 这是一个多行注释
  10. */
  11. rule "rule2"
  12.     when
  13.     then
  14.             System.out.println("rule2触发");
  15. end
复制代码
4.4 Pattern模式匹配

前面我们已经知道了Drools中的匹配器可以将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,那么我们就需要在规则体的LHS部分定义规则并进行模式匹配。LHS部分由一个或者多个条件组成,条件又称为pattern。
pattern的语法结构为:绑定变量名:Object(Field约束)
其中绑定变量名可以省略,通常绑定变量名的命名一般建议以$开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的Fact对象。Field约束部分是需要返回true或者false的0个或多个表达式。
例如我们的入门案例中:
  1. //规则二:所购图书总价在100到200元的优惠20元
  2. rule "book_discount_2"
  3.     when
  4.             //Order为类型约束,originalPrice为属性约束
  5.         $order:Order(originalPrice < 200 && originalPrice >= 100)
  6.     then
  7.         $order.setRealPrice($order.getOriginalPrice() - 20);
  8.         System.out.println("成功匹配到规则二:所购图书总价在100到200元的优惠20元");
  9. end
复制代码
通过上面的例子我们可以知道,匹配的条件为:
1、工作内存中必须存在Order这种类型的Fact对象-----类型约束
2、Fact对象的originalPrice属性值必须小于200------属性约束
3、Fact对象的originalPrice属性值必须大于等于100------属性约束
以上条件必须同时满足当前规则才有可能被激活。
绑定变量既可以用在对象上,也可以用在对象的属性上。例如上面的例子可以改为:
  1. //规则二:所购图书总价在100到200元的优惠20元
  2. rule "book_discount_2"
  3.     when
  4.         $order:Order($op:originalPrice < 200 && originalPrice >= 100)
  5.     then
  6.         System.out.println("$op=" + $op);
  7.         $order.setRealPrice($order.getOriginalPrice() - 20);
  8.         System.out.println("成功匹配到规则二:所购图书总价在100到200元的优惠20元");
  9. end
复制代码
LHS部分还可以定义多个pattern,多个pattern之间可以使用and或者or进行连接,也可以不写,默认连接为and。
  1. //规则二:所购图书总价在100到200元的优惠20元
  2. rule "book_discount_2"
  3.     when
  4.         $order:Order($op:originalPrice < 200 && originalPrice >= 100) and
  5.         $customer:Customer(age > 20 && gender=='male')
  6.     then
  7.         System.out.println("$op=" + $op);
  8.         $order.setRealPrice($order.getOriginalPrice() - 20);
  9.         System.out.println("成功匹配到规则二:所购图书总价在100到200元的优惠20元");
  10. end
复制代码
4.5 比较操作符

Drools提供的比较操作符,如下表:
[table][tr]符号说明[/tr][tr][td]>[/td][td]大于[/td][/tr][tr][td]</tdtd小于/td/trtrtd>=[/td][td]大于等于[/td][/tr][tr][td] 10)    then        $s.setAge(25);        update($s);//更新数据,导致相关的规则会重新匹配        System.out.println("规则rule_student_age小于20岁同时大于10岁触发");endrule "rule_student_age大于20岁"    when        $s:Student(age > 20)    then        System.out.println("规则rule_student_age大于20岁触发");end[/code]第二步:编写单元测试
  1. package com.itheima.drools.entity;
  2. import java.util.List;
  3. /**
  4. * 实体类
  5. * 用于测试比较操作符
  6. */
  7. public class ComparisonOperatorEntity {
  8.     private String names;
  9.     private List<String> list;
  10.     public String getNames() {
  11.         return names;
  12.     }
  13.     public void setNames(String names) {
  14.         this.names = names;
  15.     }
  16.     public List<String> getList() {
  17.         return list;
  18.     }
  19.     public void setList(List<String> list) {
  20.         this.list = list;
  21.     }
  22. }
复制代码
通过控制台的输出可以看到规则文件中定义的三个规则都触发了。
在更新数据时需要注意防止发生死循环。
4.8.2 insert方法

insert方法的作用是向工作内存中插入数据,并让相关的规则重新匹配。
第一步:修改student.drl文件内容如下
  1. package comparisonOperator
  2. import com.itheima.drools.entity.ComparisonOperatorEntity
  3. /*
  4. 当前规则文件用于测试Drools提供的比较操作符
  5. */
  6. //测试比较操作符contains
  7. rule "rule_comparison_contains"
  8.     when
  9.         ComparisonOperatorEntity(names contains "张三")
  10.         ComparisonOperatorEntity(list contains names)
  11.     then
  12.         System.out.println("规则rule_comparison_contains触发");
  13. end
  14. //测试比较操作符not contains
  15. rule "rule_comparison_notContains"
  16.     when
  17.         ComparisonOperatorEntity(names not contains "张三")
  18.         ComparisonOperatorEntity(list not contains names)
  19.     then
  20.         System.out.println("规则rule_comparison_notContains触发");
  21. end
  22. //测试比较操作符memberOf
  23. rule "rule_comparison_memberOf"
  24.     when
  25.         ComparisonOperatorEntity(names memberOf list)
  26.     then
  27.         System.out.println("规则rule_comparison_memberOf触发");
  28. end
  29. //测试比较操作符not memberOf
  30. rule "rule_comparison_notMemberOf"
  31.     when
  32.         ComparisonOperatorEntity(names not memberOf list)
  33.     then
  34.         System.out.println("规则rule_comparison_notMemberOf触发");
  35. end
  36. //测试比较操作符matches
  37. rule "rule_comparison_matches"
  38.     when
  39.         ComparisonOperatorEntity(names matches "张.*")
  40.     then
  41.         System.out.println("规则rule_comparison_matches触发");
  42. end
  43. //测试比较操作符not matches
  44. rule "rule_comparison_notMatches"
  45.     when
  46.         ComparisonOperatorEntity(names not matches "张.*")
  47.     then
  48.         System.out.println("规则rule_comparison_notMatches触发");
  49. end
复制代码
第二步:编写单元测试
  1. //测试比较操作符
  2. @Test
  3. public void test2(){
  4.     KieServices kieServices = KieServices.Factory.get();
  5.     KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
  6.     KieSession kieSession = kieClasspathContainer.newKieSession();
  7.     ComparisonOperatorEntity comparisonOperatorEntity = new ComparisonOperatorEntity();
  8.     comparisonOperatorEntity.setNames("张三");
  9.     List<String> list = new ArrayList<String>();
  10.     list.add("张三");
  11.     list.add("李四");
  12.     comparisonOperatorEntity.setList(list);
  13.     //将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配,如果规则匹配成功则执行规则
  14.     kieSession.insert(comparisonOperatorEntity);
  15.     kieSession.fireAllRules();
  16.     kieSession.dispose();
  17. }
复制代码
通过控制台输出可以发现,四个规则都触发了,这是因为首先进行规则匹配时只有第一个规则可以匹配成功,但是在第一个规则中向工作内存中插入了一个数据导致重新进行规则匹配,此时第二个规则可以匹配成功。在第二个规则中进行了数据修改导致第三个规则也可以匹配成功,以此类推最终四个规则都匹配成功并执行了。
4.8.3 retract方法

retract方法的作用是删除工作内存中的数据,并让相关的规则重新匹配。
第一步:修改student.drl文件内容如下
  1. //测试执行指定规则
  2.     @Test
  3.     public void test3(){
  4.         KieServices kieServices = KieServices.Factory.get();
  5.         //获得Kie容器对象
  6.         KieContainer kieContainer = kieServices.newKieClasspathContainer();
  7.         //从Kie容器对象中获取会话对象
  8.         KieSession session = kieContainer.newKieSession();
  9.         //Fact对象,事实对象
  10.         ComparisonOperatorEntity fact = new ComparisonOperatorEntity();
  11.         fact.setNames("李四");
  12.         List<String> list = new ArrayList<String>();
  13.         list.add("张三2");
  14.         //list.add("李四");
  15.         fact.setList(list);
  16.         session.insert(fact);
  17.         //激活规则,由Drools框架自动进行规则匹配,如果规则匹配成功,则执行当前规则
  18.         //使用框架提供的规则过滤器执行指定规则
  19.         session.fireAllRules(new RuleNameEqualsAgendaFilter("rule_comparison_notcontains"));
  20.         //session.fireAllRules(new RuleNameStartsWithAgendaFilter("rule_"));
  21.         //关闭会话
  22.         session.dispose();
  23.     }
复制代码
第二步:编写单元测试
  1. //测试比较操作符
  2. @Test
  3. public void test2(){
  4.     KieServices kieServices = KieServices.Factory.get();
  5.     KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
  6.     KieSession kieSession = kieClasspathContainer.newKieSession();
  7.     ComparisonOperatorEntity comparisonOperatorEntity = new ComparisonOperatorEntity();
  8.     comparisonOperatorEntity.setNames("张三");
  9.     List<String> list = new ArrayList<String>();
  10.     list.add("张三");
  11.     list.add("李四");
  12.     comparisonOperatorEntity.setList(list);
  13.     //将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配,如果规则匹配成功则执行规则
  14.     kieSession.insert(comparisonOperatorEntity);
  15.     kieSession.fireAllRules();
  16.     kieSession.dispose();
  17. }
复制代码
通过控制台输出可以发现,只有第一个规则触发了,因为在第一个规则中将工作内存中的数据删除了导致第二个规则并没有匹配成功。
全套代码及资料全部完整提供,点此处下载

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

麻花痒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表