规则属性

规则属性

1.no-loop

默认值:false

类型:Boolean

说明:防止死循环,当规则通过类似update这样的函数修改了Fact对象时,可以会使规则再次被激活,从而导致死循环。设置no-loop为true可以避免当前规则then部分被修改后的Fact对象再次被激活。从而防止死循环的发生。

规则内容:

1 rule "testNoLoop1"
2     when
3         $p:Person(age == 30);
4     then
5            $p.setAge("30");
6            update($p);
7            System.out.println("testNoLoop1 不设置 no-loop时的效果");
8 end

配置文件内容:

1 <kbase name="isNoLoop" packages="rules.testNoLoop">
2     <ksession name="isNoLoop"/>
3 </kbase>

Java调用代码:

 1     @Test
 2     public void testNoLoop1() {
 3         KieSession ks = kc.newKieSession("isNoLoop");
 4         Person person = new Person();
 5         person.setName("张三");
 6         person.setAge("30");
 7         person.setClassName("一班");
 8         ks.insert(person);
 9         int count = ks.fireAllRules();
10         System.out.println("总执行了" + count + "条规则");
11         ks.dispose();
12     }

结果:

testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果
testNoLoop1 不设置 no-loop时的效果

出现了死循环,重新修改规则内容:

 1 rule "testNoLoop2"
 2     no-loop true
 3     when
 4         $p:Person(age == 30);
 5     then
 6            $p.setAge("30");
 7            update($p);
 8            System.out.println("testNoLoop1 不设置 no-loop时的效果");
 9 
10 end

使用no-loop true的结果:

1 2019-08-03 14:58:01 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 testNoLoop1 设置 no-loop时的效果
3 2019-08-03 14:58:01 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
4 2019-08-03 14:58:01 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
5 总执行了1条规则
6 2019-08-03 14:58:01 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

继续修改规则内容:

 1 rule "testNoLoop3"
 2     no-loop true
 3     when
 4         $p:Person(name == "张三");
 5     then
 6            $p.setAge("30");
 7            update($p);
 8            System.out.println("testNoLoop3 设置 no-loop时的效果");
 9 
10 end
11 
12 rule "testNoLoop4"
13     no-loop true
14     when
15         $p:Person(age == 30);
16     then
17            $p.setName("张三");
18            update($p);
19            System.out.println("testNoLoop4 设置 no-loop时的效果");
20 
21 end

结果:

 1 testNoLoop3 设置 no-loop时的效果
 2 testNoLoop4 设置 no-loop时的效果
 3 testNoLoop3 设置 no-loop时的效果
 4 testNoLoop4 设置 no-loop时的效果
 5 testNoLoop3 设置 no-loop时的效果
 6 testNoLoop4 设置 no-loop时的效果
 7 testNoLoop3 设置 no-loop时的效果
 8 testNoLoop4 设置 no-loop时的效果
 9 testNoLoop3 设置 no-loop时的效果
10 testNoLoop4 设置 no-loop时的效果
11 testNoLoop3 设置 no-loop时的效果
12 testNoLoop4 设置 no-loop时的效果
13 testNoLoop3 设置 no-loop时的效果
14 testNoLoop4 设置 no-loop时的效果
15 testNoLoop3 设置 no-loop时的效果
16 testNoLoop4 设置 no-loop时的效果

说明:从以上结果看出:只有在事实对象发生了变化时,才会出现死循环。如果在LHS部分的比较值不是update修改的值,会不会有问题呢?

继续修改规则内容:

 1 rule "testNoLoop5"
 2     // no-loop true
 3     when
 4         $p:Person(name == "张三");
 5     then
 6            $p.setAge("30");
 7            update($p);
 8            System.out.println("testNoLoop5 没有设置 no-loop时的效果");
 9 
10 end

结果:

1 2019-08-03 15:11:32 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 testNoLoop5 没有设置 no-loop时的效果
3 2019-08-03 15:11:32 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
4 2019-08-03 15:11:32 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
5 总执行了1条规则
6 2019-08-03 15:11:32 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

没有死循环,继续修改规则内容:

 1 testNoLoop6 没有设置 no-loop时的效果
 2 testNoLoop6 没有设置 no-loop时的效果
 3 testNoLoop6 没有设置 no-loop时的效果
 4 testNoLoop6 没有设置 no-loop时的效果
 5 testNoLoop6 没有设置 no-loop时的效果
 6 testNoLoop6 没有设置 no-loop时的效果
 7 testNoLoop6 没有设置 no-loop时的效果
 8 testNoLoop6 没有设置 no-loop时的效果
 9 testNoLoop6 没有设置 no-loop时的效果
10 testNoLoop6 没有设置 no-loop时的效果
11 testNoLoop6 没有设置 no-loop时的效果
12 testNoLoop6 没有设置 no-loop时的效果

在一个规则文件中,一个事实对象通过Drools函数被修改了,规则体将被再次激活。前提条件是被修改的对象与规则LHS部分的约束条件有一种包含的关系。导致了规则重新被激活和匹配。

 2.lock-on-active

默认值:false

类型:Boolean

它是规则体中的一个属性,顾名思义,是用来锁定规则的,而且是用来锁定活跃的规则的。当设置这个属性的值为true的时候,被设置的规则只会被触发一次。之后,无论怎么去更新Fact对象,当前规则也只能够被触发一次。它相当于是no-loop的一个升级的版本。一个更为强大的去解决死循环的属性。

示例:

创建规则内容:

 1 package rules.isLockNoActive;
 2 import com.entity.Person;
 3 
 4 rule "testLockNoActive1"
 5     lock-on-active true
 6     when
 7         $p:Person(name=="张三");
 8     then
 9         $p.setAge("30");
10         update($p);
11         System.out.println("testLockNoActive1 设置 lock-on-active 的效果");
12 end
13 
14 rule "testLockNoActive2"
15     lock-on-active true
16     when
17         $p:Person(age=="30");
18     then
19         $p.setName("张三");
20         update($p);
21         System.out.println("testLockNoActive2 设置 lock-on-active 的效果");
22 end

在kmodule.xml文件中继续添加:

<kbase name="isLockNoActive" packages="rules.isLockNoActive">
       <ksession name="isLockNoActive"/>
</kbase>

接着创建java端的调用代码:

 1     @Test
 2     public void testLockOnActive() {
 3         KieServices kss = KieServices.Factory.get();
 4         KieContainer kc = kss.getKieClasspathContainer();
 5         KieSession ks = kc.newKieSession("isLockNoActive");
 6         Person person = new Person();
 7         person.setName("张三");
 8         person.setAge("30");
 9         person.setClassName("一班");
10         ks.insert(person);
11         int count = ks.fireAllRules();
12         System.out.println("总共执行了" + count + "条规则");
13         ks.dispose();
14     }

看下结果:

2019-08-04 15:59:56 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
testLockNoActive1 设置 lock-on-active 的效果
testLockNoActive2 设置 lock-on-active 的效果
2019-08-04 15:59:56 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
2019-08-04 15:59:56 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
总共执行了2条规则
2019-08-04 15:59:56 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

从结果中,可以清楚的看到,和no-loop实现的效果是一样的。

3.salience

默认值:0

类型:Integer

规则体执行的顺序。每一个规则体都有一个默认的执行顺序。在没有设置这个属性的情况下,执行顺序是由上到下的。这个属性的值是一个整数,它的值越大,执行就越是靠前。另外,Drools支持动态的去配置优先级。

示例:

创建规则内容:

 1 package rules.isSalience;
 2 rule "testSalience1"
 3 salience 1
 4     when
 5         eval(true);
 6     then
 7         System.out.println("hello world salience 1");
 8 end
 9 
10 rule "testSalience2"
11 salience 2
12     when
13         eval(true);
14     then
15         System.out.println("hello world salience 2");
16 end
17 
18 rule "testSalience3"
19 salience 5
20     when
21         eval(true);
22     then
23         System.out.println("hello world salience 5");
24 end

在kmodule.xml文件中继续添加下面的内容:

1     <kbase name="isSalience" packages="rules.isSalience">
2         <ksession name="isSalience"/>
3     </kbase>

创建java端的调用代码:

1    @Test
2     public void testSalience() {
3         KieServices kss = KieServices.Factory.get();
4         KieContainer kc = kss.getKieClasspathContainer();
5         KieSession ks = kc.newKieSession("isSalience");
6         int count = ks.fireAllRules();
7         System.out.println("总共执行了" + count + "条规则");
8         ks.dispose();
9     }

运行结果:

1 2019-08-04 16:16:27 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 hello world salience 5
3 hello world salience 2
4 hello world salience 1
5 2019-08-04 16:16:27 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
6 2019-08-04 16:16:27 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
7 总共执行了3条规则
8 2019-08-04 16:16:27 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

从运行的结果中可以看到:是严格按照salience设置的属性值顺序执行的。

再测试下动态的salience,编写规则内容:

1 rule "testSalience4"
2 salience (Math.random() * 10 + 1)
3     when
4         eval(true);
5     then
6         System.out.println("hello world salience nothing");
7 end

运行结果:

1 2019-08-04 16:21:34 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 hello world salience nothing
3 hello world salience 5
4 hello world salience 2
5 hello world salience 1
6 2019-08-04 16:21:34 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
7 2019-08-04 16:21:34 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
8 总共执行了4条规则
9 2019-08-04 16:21:34 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

 4.activation-group

默认值:N/A

类型:String

从字面上来说,是指激活分组。通过字符串去定义分组名称。具有相同组名称的规则体有且只有一个规则被激活。其他规则体的LHS就算是true也不会再被执行。这个属性受到salience属性的影响。但是如果当前的规则文件中的其他规则没有为这个属性赋值,可以认为规则是处于被激活状态的,不会受到该属性的影响。

创建规则内容:

 1 package rules.isActivationGroup;
 2 rule "testActivationGroup1"
 3     activation-group "testGroup"
 4     when
 5         eval(true);
 6     then
 7         System.out.println("规则 testActivationGroup1 设置 activation-group \"testGroup\"");
 8 end
 9 rule "testActivationGroup2"
10     activation-group "testGroup"
11     when
12         eval(true);
13     then
14         System.out.println("规则 testActivationGroup2 设置 activation-group \"testGroup\"");
15 end

继续在配置文件中添加:

    <kbase name="isActivationGroup" packages="rules.isActivationGroup">
        <ksession name="isActivationGroup"/>
    </kbase>

结果显而易见:

2019-08-06 00:00:16 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
规则 testActivationGroup1 设置 activation-group "testGroup"
2019-08-06 00:00:16 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
2019-08-06 00:00:16 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
总共执行了1条规则
2019-08-06 00:00:16 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

但是,如果多执行几次就会发现,输出结果一直都是rule testActivationGroup1的RHS部分。

其实,有两种方式可以使得输出的结果变为testActivationGroup2.

1.第一种是根据规则匹配的特性,设置testActivation规则的LHS部分设置成false。2.设置salience属性。

创建规则文件:

rule "testActivationGroup3"
    salience 10
    activation-group "testGroup2"
    when
        eval(true);
    then
        System.out.println("规则 testActivationGroup3 salience 10 设置 activation-group \"testGroup\"");
end
rule "testActivationGroup4"
    salience 20
    activation-group "testGroup2"
    when
        eval(true);
    then
        System.out.println("规则 testActivationGroup3 salience 20 设置 activation-group \"testGroup\"");
end

测试代码不变,看下结果

1 规则 testActivationGroup3 salience 20 设置 activation-group "testGroup"
2 2019-08-06 00:06:10 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
3 2019-08-06 00:06:10 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
4 总共执行了1条规则
5 2019-08-06 00:06:10 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

由于salience 20 的优先级高于salience 10 ,所以输出结果发生了变化。

5.dialect

属性值:可能是Java 或者 Mvel。

类型:String。

定义规则中要使用的语言类型。默认情况下是有包指定的。

6.duration

默认值:无

类型:long

定时器。含义是如果当前的规则LHS部分结果是true,就继续执行。这个属性已经被弃用了。

7.属性agenda-group

默认值:没有

类型:String

说明:可以通过配置这个属性来控制规则的执行,而且只有获得焦点的规则才会被激活。

创建规则内容:

 1 package rules.isAgendaGroup;
 2 
 3 rule "testisAgendaGroup1"
 4     agenda-group "ag1"
 5     when
 6         eval(true);
 7     then
 8         System.out.println("testisAgendaGroup1 设置属性 agenda-group \"ag1\"");
 9 end
10 
11 rule "testisAgendaGroup2"
12     agenda-group "ag2"
13     when
14         eval(true);
15     then
16         System.out.println("testisAgendaGroup2 设置属性 agenda-group \"ag2\"");
17 end

在配置文件中添加:

1 <kbase name="isAgendaGroup" packages="rules.isAgendaGroup">
2         <ksession name="isAgendaGroup"/>
3     </kbase>

创建调用代码:

 1     @Test
 2     public void testAgendaGroup() {
 3         KieServices kss = KieServices.Factory.get();
 4         KieContainer kc = kss.getKieClasspathContainer();
 5         KieSession ks = kc.newKieSession("isAgendaGroup");
 6         ks.getAgenda().getAgendaGroup("ag1").setFocus();
 7         int count = ks.fireAllRules();
 8         System.out.println("总共执行了" + count + "条规则");
 9         ks.dispose();
10     }

运行结果:

1 2019-08-06 22:08:41 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 testisAgendaGroup1 设置属性 agenda-group "ag1"
3 2019-08-06 22:08:41 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
4 2019-08-06 22:08:41 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
5 总共执行了1条规则
6 2019-08-06 22:08:41 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

继续再添加规则内容如下:

1 rule "testisAgendaGroup3"
2     agenda-group "ag1"
3     when
4         eval(true);
5     then
6         System.out.println("testisAgendaGroup3 设置属性 agenda-group \"ag1\"");
7 end

执行测试代码,结果:

1 2019-08-06 22:12:48 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 testisAgendaGroup1 设置属性 agenda-group "ag1"
3 testisAgendaGroup3 设置属性 agenda-group "ag1"
4 2019-08-06 22:12:48 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
5 2019-08-06 22:12:48 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
6 总共执行了2条规则
7 2019-08-06 22:12:48 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

可以看到,如果agenda-group设置的属性值是相同的,那么这些规则都是可以被激活的。

属性agenda-group属性会受到其他属性的影响。

1.第一种情况

 1 rule "testagag1"
 2     agenda-group "ag1"
 3     activation-group "agag"
 4     when
 5         eval(true);
 6     then
 7         System.out.println("testagag1 设置属性 agenda-group \"ag1\" activation-group \"agag\"");
 8 end
 9 
10 rule "testagag2"
11     activation-group "agag"
12     agenda-group "ag1"
13    
14     when
15         eval(true);
16     then
17         System.out.println("testagag2 设置属性 agenda-group \"ag1\" activation-group \"agag\"");
18 end

结果:

1 2019-08-06 22:22:19 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
2 testagag1 设置属性 agenda-group "ag1" activation-group "agag"
3 2019-08-06 22:22:19 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
4 2019-08-06 22:22:19 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
5 总共执行了1条规则
6 2019-08-06 22:22:19 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

只会执行其中的一个规则。执行顺序可以根据优先级去设置,默认的会由上到下。

2.第二种情况

rule "testagag3"
    agenda-group "ag6"
    activation-group "agag1"
    when
        eval(true);
    then
        System.out.println("testagag3 设置属性 agenda-group \"ag6\" activation-group \"agag1\"");
end

rule "testagag4"
    agenda-group "ag6"
    activation-group "agag2"
    when
        eval(true);
    then
        System.out.println("testagag3 设置属性 agenda-group \"ag6\" activation-group \"agag2\"");
end

调用代码:

 @Test
    public void testAgendaGroup2() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        KieSession ks = kc.newKieSession("isAgendaGroup");
        ks.getAgenda().getAgendaGroup("ag6").setFocus();
        int count = ks.fireAllRules();
        System.out.println("总共执行了" + count + "条规则");
        ks.dispose();
    }

结果:

2019-08-06 22:27:20 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
testagag3 设置属性 agenda-group "ag6" activation-group "agag1"
testagag3 设置属性 agenda-group "ag6" activation-group "agag2"
2019-08-06 22:27:20 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
2019-08-06 22:27:20 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
总共执行了2条规则
2019-08-06 22:27:20 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

从结果中可以看到, 会执行多个规则,但是只有获得focus的规则才可以被激活,得到执行的机会。

3.第三种情况

创建规则内容:

 1 rule "testagag6"
 2     agenda-group "ag9"
 3     activation-group "agag2"
 4     when
 5         eval(true);
 6     then
 7         System.out.println("testagag3 设置属性 agenda-group \"ag9\" activation-group \"agag2\"");
 8 end
 9 
10 rule "testagag5"
11     agenda-group "ag8"
12     activation-group "agag1"
13     when
14         eval(true);
15     then
16         System.out.println("testagag3 设置属性 agenda-group \"ag8\" activation-group \"agag1\"");
17 end
 1 rule "testagag6"
 2     agenda-group "ag9"
 3     activation-group "agag2"
 4     when
 5         eval(true);
 6     then
 7         System.out.println("testagag3 设置属性 agenda-group \"ag9\" activation-group \"agag2\"");
 8 end
 9 
10 rule "testagag5"
11     agenda-group "ag8"
12     activation-group "agag1"
13     when
14         eval(true);
15     then
16         System.out.println("testagag3 设置属性 agenda-group \"ag8\" activation-group \"agag1\"");
17 end

测试代码:

@Test
    public void testAgendaGroup3() {
        KieServices kss = KieServices.Factory.get();
        KieContainer kc = kss.getKieClasspathContainer();
        KieSession ks = kc.newKieSession("isAgendaGroup");
        ks.getAgenda().getAgendaGroup("ag9").setFocus();
        int count = ks.fireAllRules();
        System.out.println("总共执行了" + count + "条规则");
        ks.dispose();
    }

结果:

2019-08-06 22:35:04 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now FIRING_ALL_RULES
testagag3 设置属性 agenda-group "ag9" activation-group "agag2"
2019-08-06 22:35:04 [DEBUG]org.drools...DefaultAgenda - State was FIRING_ALL_RULES is now HALTING
2019-08-06 22:35:04 [DEBUG]org.drools...DefaultAgenda - State was HALTING is now INACTIVE
总共执行了1条规则
2019-08-06 22:35:04 [DEBUG]org.drools...DefaultAgenda - State was INACTIVE is now DISPOSED

只有获得焦点的规则才可以得到执行的机会。

8.auto-focus

默认值:false

类型:Boolean

说明:可以自动获取焦点,无需再通过在Java中设置。如果一个规则被执行了,那么可以认为这个属性的值是true。一般和agenda-group结合使用。

 

还有几个属性,date-effective,date-expires是关于日期的。timer属性,类型java中定时器。

 

 



 

rule "testagag1"
agenda-group "ag1"
activation-group "agag"
when
eval(true);
then
System.out.println("testagag1 设置属性 agenda-group \"ag1\" activation-group \"agag\"");
end

rule "testagag2"
activation-group "agag"
agenda-group "ag1"

when
eval(true);
then
System.out.println("testagag2 设置属性 agenda-group \"ag1\" activation-group \"agag\"");
end
posted @ 2019-08-03 15:20  门外大汉  阅读(493)  评论(0编辑  收藏  举报