整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

数据库中的定义属性(字段)

义属性

概述

·django根据属性的类型确定以下信息

·当前选择的数据库支持字段的类型

·渲染管理表单时使用的默认html控件

·在管理站点最低限度的验证

·django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列

·属性命名限制

·遵循标识符规则

·由于django的查询方式,不允许使用连续的下划线

·定义属性时,需要字段类型,字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中

·使用方式

·导入from django.db import models

·通过models.Field创建字段类型的对象,赋值给属性

逻辑删除

·对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False

字段类型

·AutoField

·一个根据实际ID自动增长的IntegerField,通常不指定如果不指定,一个主键字段将自动添加到模型中

·CharField(max_length=字符长度)

·字符串,默认的表单样式是 TextInput

·TextField

·大文本字段,一般超过4000使用,默认的表单控件是Textarea

·IntegerField

·整数

·DecimalField(max_digits=None, decimal_places=None)

·使用python的Decimal实例表示的十进制浮点数

·参数说明

·DecimalField.max_digits

·位数总数

·DecimalField.decimal_places

·小数点后的数字位数

·FloatField

·用Python的float实例来表示的浮点数

·BooleanField

·true/false 字段,此字段的默认表单控制是CheckboxInput

·NullBooleanField

·支持null、true、false三种值

·DateField([auto_now=False, auto_now_add=False])

·使用Python的datetime.date实例表示的日期

·参数说明

·DateField.auto_now

·每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false

·DateField.auto_now_add

·当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false

·说明

·该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,包含了一个额外的invalid_date错误消息键

·注意

·auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果

·TimeField

·使用Python的datetime.time实例表示的时间,参数同DateField

·DateTimeField

·使用Python的datetime.datetime实例表示的日期和时间,参数同DateField

·FileField

·一个上传文件的字段

·ImageField

·继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image

字段选项

·概述

·通过字段选项,可以实现对字段的约束

·在字段对象时通过关键字参数指定

·null

·如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False

·blank

·如果为True,则该字段允许为空白,默认值是 False

·注意

·null是数据库范畴的概念,blank是表单验证证范畴的

·db_column

·字段的名称,如果未指定,则使用属性的名称

·db_index

·若值为 True, 则在表中会为此字段创建索引

·default

·默认值

·primary_key

·若为 True, 则该字段会成为模型的主键字段

·unique

·如果为 True, 这个字段在表中必须有唯一值

关系

·分类

·ForeignKey:一对多,将字段定义在多的端中

·ManyToManyField:多对多,将字段定义在两端中

·OneToOneField:一对一,将字段定义在任意一端中

·用一访问多

·格式

·对象.模型类小写_set

·示例

grade.students_set

·用一访问一

·格式

·对象.模型类小写

·示例

·grade.students

·访问id

·格式

·对象.属性_id

·示例

·student.sgrade_id

JavaScript 类型是在java.util.Date类的基础上建立起来的。所以,Date类型使用的是UTC, 又称世界统一时间,使用自1970年1月1日起经过的毫秒数来保存,可以精确到之后的285616年。

//创建一个日期对象

var date = new Date();

console.log(date); //FireFox: Wed Nov 07 2018 21:31:23 GMT+0800

//Chrome: Wed Nov 07 2018 21:31:23 GMT+0800 (中国标准时间)

//IE: Wed Nov 07 21:31:23 UTC+0800 2018

//Opera: Wed Nov 07 2018 21:31:23 GMT+0800

构造方法中可以传递参数,指定需要的时间,如果没有传参数,就默认使用当前的时间。调用Date构造方法不传递参数时,新实例化的对象自动获取当前的日期时间,但是在不同的浏览器上显示的结果是有区别的,如上所示。

ECMAScript 中有两个方法,分别是 Date.parse() 和 Date.UTC(), 这两个方法属于静态方法,不需要进行实例化。 Date.parse()方法接收一个日期格式的参数,并根据这个字符串返回相应的毫秒数。例如:

console.log(Date.parse("4/12/2007")); //返回一个毫秒数。毫秒数1176307200000, 各 个浏览器相同。

但是返回的这个值对于我们来说是不容易理解的,所以可以返回我们能够看得懂的值。如下:

var date = new Date(Date.parse("4/12/2007"));

console.log(date); //Thu Apr 12 2007 00:00:00 GMT+0800

还可以这样写:

var date = new Date(1176307200000); //注意参数当中是数字

console.log(date); //Thu Apr 12 2007 00:00:00 GMT+0800

如果参数变成字符串数字,如下:

var date = new Date("1176307200000"); //注意参数当中是字符串

console.log(date); //Invalid Date

当然可以这样写,var date = new Date("4/12/2007"); console.log(date);

//Thu Apr 12 2007 00:00:00 GMT+0800, 默认后台自动调用Date.parse() 方法。

关于更多日期和时间的用法,请关注下期的更新。

、介绍

规则属性是您可以添加到业务规则以修改规则行为的附加规范。 在 DRL 文件中,您通常在规则条件和操作的上方定义规则属性,多个属性位于单独的行中,格式如下:

rule "rule_name"
    // Attribute
    // Attribute
    when
        // Conditions
    then
        // Actions
end

二、常见的规则属性

规则属性

解释

举例

salience

定义规则优先级,是一个整数。当在激活队列中排序时,salience的值越大,优先级越高

salience 99

enabled

定义规则是否启用. true 启用,false 禁用,默认值是true

enabled true

date-effective

包含时间和日期的字符串,当当前时间大于date-effective时,该规则才会被激活。这个时间格式可以修改,见下方具体的用法

date-effective "4-5月-2022"

date-expires

设置规则的过期时间,时间格式和上方一样。

date-expires "4-5月-2022"

no-loop

布尔值,默认值为false, 定义当当前规则规则的结果修改了fact对象时,是否可以再次执行该规则。true:不可以, false:可以,可能会导致死循环。指的是当前规则的修改,如果别的规则修改了,还会导致该规则的触发

no-loop true

agenda-group

Agenda groups允许您对agenda进行分区,以提供对规则组的更多执行控制。 只有获得焦点的议程组中的规则才能被激活。 ,但是这个里面有个特例,如果某个规则没有配置 agenda-group,但是它模式匹配成功了,那么会被分到默认的组(main),这个main组的规则也会执行。

agenda-group "GroupName"

auto-focus

布尔值,仅适用于Agenda-Group内的规则。当值为true时,下次激活该规则时,会将焦点自动给这个Agenda group

auto-focus true

activation-group

表示该组下的规则只有一个规则会被执行,该组下其余激活的规则会被取消执行。 但是别的组激活的规则可能会被执行。

activation-group "GroupName"

duration

long类型的值,如果在这个时间之后规则还成立,那么执行该规则

duration 1000

timer

一个字符串,标识用于调度规则的 int(间隔)或 cron 计时器定义。

Example: timer ( cron:* 0/15 * * * ? ) (every 15 minutes)

calendar

定义Quartz calendar用于调度规则。


lock-on-active

一个布尔值,仅适用于规则流组或议程组中的规则。 选择该选项后,下次规则的规则流组变为活动状态或规则的议程组获得焦点时,规则无法再次激活,直到规则流组不再处于活动状态或议程组失去焦点。 这是 no-loop 属性的更强版本,因为匹配规则的激活被丢弃,无论更新的来源如何(不仅是规则本身)。 此属性非常适合计算规则,其中您有许多修改事实的规则并且您不希望任何规则重新匹配和再次触发。

lock-on-active true

dialect

将 JAVA 或 MVEL 标识为用于规则中的代码表达式的语言的字符串。 默认情况下,该规则使用在包级别指定的方言。 此处指定的任何方言都会覆盖该规则的包方言设置。

dialect "JAVA"

三、部分规则属性案例

此处编写出规则文件和部分核心Java代码


项目结构

1、salience

定义规则执行的优先级,salience的值越大,优先级越高

1、规则文件的编写

rule "salience_rule_1"
    salience 4
    when
    then
        System.out.println("rule 1");
end

rule "salience_rule_2"
    salience 3
    when
    then
        System.out.println("rule 2");
end

// 此处优先级的值是动态获取来的
rule "salience_rule_3"
    salience $dynamicSalience
    when
        $dynamicSalience: Integer()
    then
        System.out.println("rule 3");
end

注意:
我们的salience_rule_3的优先级的值是动态来的,即是从工作内存中获取的。

2、java代码编写

public class DroolsSalienceApplication {
    public static void main(String[] args) {
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");

        // 向工作内存中插入一个Integer值,salience_rule_3 需要用到这个优先级
        kieSession.insert(10);

        // 只匹配规则名称是已 salience_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("salience_"));

        kieSession.dispose();
    }
}

kieSession.insert(10);此处向工作内存中插入一个值,将会匹配到salience_rule_3,然后动态修改它的优先级。

3、运行结果

rule 3
rule 1
rule 2

因为 salience 的值越大优先级越高,所以是这个顺序。

2、enabled

定义规则是否启用,true启用 false禁用

1、规则文件编写

package rules

rule "enabled_rule_1"
    // 禁用此规则
    enabled false
    when
    then
        System.out.println("enabled_rule_1");
end

rule "enabled_rule_2"
    // 启用此规则,默认就是启用
    enabled true
    when
    then
        System.out.println("enabled_rule_2");
end

enabled_rule_2这个规则需要运行,enabled_rule_1这个规则不能运行。

2、java代码编写

/**
 * 测试规则的启用和禁用
 */
public class DroolsEnabledApplication {
    public static void main(String[] args) {
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 只匹配规则名称是已 enabled_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("enabled_"));
        kieSession.dispose();
    }
}

没有需要注意的地方

3、运行结果

enabled_rule_2

可以看到只有规则enabled_rule_2输出了结果,而enabled_rule_1被禁用了。

3、date-effective

定义规则什么时候启用,只有当前时间>规则时间才会启用。需要注意默认的时间格式,可以通过java代码进行修改。

1、规则文件编写

package rules
import java.text.SimpleDateFormat
import java.util.Date

// 规则一:输出当前时间
rule "date_effective_rule_1"
    when
    then
        System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end

// 规则二: 该规则会在2022-05-18 10:54:26之后被激活
rule "date_effective_rule_2"
    date-effective "2022-05-18 10:54:26"
    when
    then
        System.out.println("date_effective_rule_2执行了,规则允许被执行的时间应该在2022-05-18 10:54:26之后");
end

// 规则三: 该规则会在2023-05-18 10:54:26之后被激活
rule "date_effective_rule_3"
    date-effective "2023-05-18 10:54:26"
    when
    then
        System.out.println("date_effective_rule_3会在时间到了2023-05-18 10:54:26才激活");
end

规则一:输出当前时间
规则二: 该规则会在2022-05-18 10:54:26之后被激活
规则三: 该规则会在2023-05-18 10:54:26之后被激活

2、java代码编写

/**
 * 测试规则在执行的时间之后才能执行
 */
public class DroolsDateEffectiveApplication {
    public static void main(String[] args) {
        // 设置日期格式,否则可能会报错(Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]])
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 只匹配规则名称是已 date_effective_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("date_effective_"));
        kieSession.dispose();
    }
}

需要注意System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");这句,这个修改drools中的日期格式,因为规则中写的日期格式为date-effective "2023-05-18 10:54:26"而默认的格式为d-MMM-yyyy,不修会报错。

3、运行结果

当前时间:2022-05-18 10:59:38
date_effective_rule_2执行了,规则允许被执行的时间应该在2022-05-18 10:54:26之后

可以看到规则二执行了,规则三没有执行,因为规则三需要时间到达了2023-05-18 10:54:26才执行,而当前时间不符合。

4、注意事项

如果出现了Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]]这个错误该怎么解决了,这是因为日期格式不正确。需要在java代码中进行如下设置System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss")

4、date-expires

定义规则的过期时间,即规则到了该时间之后就不可使用了。和date-effective的用法类似,此处就不演示了。

5、no-loop

定义当当前规则的结果修改了fact对象时,是否可以再次执行该规则。可以防止死循环

1、规则文件编写

package rules
import java.util.concurrent.TimeUnit
import java.text.SimpleDateFormat
import java.util.Date

rule "no_loop_rule_1"
    no-loop true
    when
        $i: Integer(intValue() < 20)
    then
        modify($i){
        }
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " no_loop_rule_1 i=" + $i);
end

rule "no_loop_rule_2"
    no-loop false

    when
        $i: Integer(intValue() < 20)
    then
        modify($i){
        }
        TimeUnit.SECONDS.sleep(1);
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " no_loop_rule_2 i=" + $i);
end

解释:
no_loop_rule_1no-loop true表示如果当前规则的RHS部分,对Fact对象进行了修改,则不会再次触发该规则。那如果是no_loop_rule_2修改了,会导致该规则的触发吗?答案是会触发,如果我不想被触发呢?那么使用lock-on-active可以实现。
no_loop_rule_2no-loop false表示如果当前规则的RHS部分,对Fact对象进行了修改,那么还会再次匹配这个规则。

2、java代码编写

/**
 * 测试规则是否可以再次被执行
 */
public class DroolsNoLoopApplication {
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        kieSession.insert(10);
        // 只匹配规则名称是已 no_loop_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("no_loop_"));
        // 睡眠5s,使规则文件中的规则执行完
        TimeUnit.SECONDS.sleep(5);
        kieSession.dispose();
    }
}

此处 java 代码,睡眠了5s,是为了让规则执行。

3、运行结果

2022-05-18 11:42:29 no_loop_rule_1 i=10
2022-05-18 11:42:31 no_loop_rule_2 i=10
2022-05-18 11:42:31 no_loop_rule_1 i=10
2022-05-18 11:42:32 no_loop_rule_2 i=10

解释:
2022-05-18 11:42:29 no_loop_rule_1 i=10: no_loop_rule_1被触发,由于RHS部分使用了modify修改了规则内存中的对象,但是该规则存在 no-loop true 的属性,所以该规则没有再次被触发,即只输出了一次。

2022-05-18 11:42:30 no_loop_rule_2 i=10 2022-05-18 11:42:30 no_loop_rule_1 i=10 此时规则 no_loop_rule_2 执行了,由于该规则的 no-loop 为 false 并且使用了 modify 方法,所以该规则多次被触发了,从结果上看,貌似规则 no_loop_rule_1 又再次被触发了,不是应该不被触发吗,因为设置了no-loop true?因为这是no_loop_rule_2导致no_loop_rule_1触发的,而no_loop只对自身的RHS修改有效。

疑问:
那如果将 no-loop换成lock-on-active结果会一样吗?可以自己尝试一下看看结果。

6、agenda-group

将被模式匹配成功后的规则,进行分组,只有获得焦点的组,才可以执行规则。但是这个里面有个特列,如果某个规则在模式匹配,匹配成功了,但是没有配置agenda-group,那么它会被分配到main组,这个main组的规则总是执行的。

agenda-group的数据结构就类似stack,激活的组是在栈顶。参考如下图:


agenda-group



参考链接: https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools

1、规则文件编写

package rules

/**
    agenda-group 的数据结构类似与栈,激活的组会被放置在栈顶,
    `main`是默认组,总是存在的,即没有配置agenda-group的就是`main`,
    `main`总是会执行的。
*/

rule "agenda_group_001_rule_1"
    agenda-group "group-001"
    when
    then
        System.out.println("agenda_group_001_rule_1");
end

rule "agenda_group_001_rule_2"
    agenda-group "group-001"
    when
    then
        System.out.println("agenda_group_001_rule_2");
end

rule "agenda_group_002_rule_3"
    agenda-group "group-002"
    when
    then
        System.out.println("agenda_group_002_rule_3");
end

rule "agenda_group_no_group_rule_4"
    when
    then
        System.out.println("agenda_group_no_group_rule_4");
end

注意: 此处其实是 存在 3个组的,agenda_group_no_group_rule_4如果模式匹配成功后会被分配到main组,main总是会被执行的。

2、java代码编写

/**
 * 测试规则分组
 */
public class DroolsAgendaGroupApplication {
    public static void main(String[] args) {
        // 设置日期格式,否则可能会报错(Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]])
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");

        // 激活组
        kieSession.getAgenda().getAgendaGroup("group-001").setFocus();

        // 只匹配规则名称是已 agenda_group_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("agenda_group_"));
        kieSession.dispose();
    }
}

激活group-001分组。

3、运行结果

agenda_group_001_rule_1
agenda_group_001_rule_2
agenda_group_no_group_rule_4

解释:
agenda_group_no_group_rule_4为什么会被输出呢?它没有定义agenda-group啊,而且我们激活的也是group-001分组,它不应该输出啊。这是应为这个规则模式匹配成功后被分配到了默认的main组,而main组一定会被执行的。

7、auto-focus

设置某个agenda-group默认获取到焦点,和在java代码中使用kieSession.getAgenda().getAgendaGroup("group-001").setFocus();或在drl文件中使用drools.setFocus(..)一样。

8、activation-group

处于该分组中激活的规则,同一个组下,只有一个规则可以执行,其余的会被取消执行。但是别的组中激活的规则还是可以执行的。

1、规则文件编写

package rules

rule "activation_group_001_rule_1"
    activation-group "group-001"
    salience 1
    when
    then
        System.out.println("activation_group_001_rule_1");
end

rule "activation_group_001_rule_2"
    activation-group "group-001"
    salience 2
    when
    then
        System.out.println("activation_group_001_rule_2");
end

rule "activation_group_002_rule_3"
    activation-group "group-002"
    when
    then
        System.out.println("activation_group_002_rule_3");
end

rule "activation_group_no_group_rule_4"
    when
    then
        System.out.println("activation_group_no_group_rule_4");
end

activation-group "group-001"此处对这个组的规则指定了优先级,优先级高的先执行,执行完之后,该组别的规则不执行。

2、java代码编写

public class DroolsActivationGroupApplication {
    public static void main(String[] args) {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 只匹配规则名称是已 activation_group_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("activation_group_"));
        kieSession.dispose();
    }
}

3、运行结果

activation_group_001_rule_2
activation_group_002_rule_3
activation_group_no_group_rule_4

可以看到分组group-001中有2个规则,但是只执行了一个规则。

9、duration

long类型的值,单位毫秒,如果在这个时间之后规则还成立,那么执行该规则。

1、规则文件编写

package rules
import java.text.SimpleDateFormat
import java.util.Date

rule "duration_rule_1"
    // 延迟1s后执行规则
    duration 1000
    when
        $i: Integer(intValue() < 10)
    then
        System.out.println(Thread.currentThread().getName() + ": " + 
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+ 
        " duration_rule_1 $i:"+$i);
end

定义规则延迟1s后进行执行。

2、java代码编写

/**
 * 在多少毫秒后,如果条件还成立,则触发该规则
 */
public class DroolsDurationApplication {
    public static void main(String[] args) throws InterruptedException {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");

        FactHandle factHandle = kieSession.insert(3);
        // 只匹配规则名称是已 duration_ 开头的规则,忽略其余的规则
        new Thread(() -> {
            // 调用此方法会阻塞调用线程,直到 `kieSession.halt();`的调用
            System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            kieSession.fireUntilHalt(new RuleNameStartsWithAgendaFilter("duration_"));
        }, "fire-thread").start();

        // 如果修改这个值,使得规则的条件不成立,看规则是否还执行
        kieSession.update(factHandle, 4);

        TimeUnit.SECONDS.sleep(2);
        kieSession.halt();

        kieSession.dispose();
    }
}

注意:
1、我们调用出发所有规则执行的方法不在是fireAllRules而是fireUntilHalt
2、fireUntilHalt的调用会阻塞线程,直到调用halt方法,因此fireUntilHalt需要放置到另外的线程中调用。而且我们观察规则的执行,也是在这个线程中调用的。

3、运行结果

当前时间:2022-05-18 14:13:36
fire-thread: 2022-05-18 14:13:37 duration_rule_1 $i:4

可以看到,延迟1s后规则执行了。

4、疑问

如果我们在1s钟之内,将规则的条件修改成不成立,那么规则还执行吗?答案:不执行。

10、lock-on-active

rule flow groups or agenda groups配合使用。

需求:
我们有2个规则,并且同属于一个组,规则二执行完之后,工作内存中的Fact对象的值发生了变化,导致规则一满足执行的条件,而规则一已经执行一遍了,此处需要阻止规则二的触发导致规则一的出触发。使用
lock-on-active 即可实现。

1、规则文件编写

package rules

import com.huan.drools.lockonactive.Person

rule "lock_on_active_rule_01"
    agenda-group "group-001"
    lock-on-active true
    when
        $p: Person(age < 18)
    then
        System.out.println("lock_on_active_rule_01: 用户:[" + $p.getName() + "]当前的年龄是:[" + $p.getAge() + "]");
 end

rule "lock_on_active_rule_02"
    agenda-group "group-001"
    when
        $p: Person(name == "张三")
    then
        modify($p){
            setAge(15)
        }
        System.out.println("lock_on_active_rule_02: 用户:[" + $p.getName() + "]当前的年龄是:[" + $p.getAge() + "]");
end

规则lock_on_active_rule_01加了lock-on-active true属性后,规则lock_on_active_rule_02修改Fact导致规则lock_on_active_rule_01的条件成立,此时规则也是不会执行的。

2、java代码编写

/**
 * 一个简单的实体类
 *
 * @author huan.fu
 * @date 2022/5/18 - 14:34
 */
@Getter
@Setter
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
}

public class DroolsLockOnActiveApplication {
    public static void main(String[] args) {
        System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
        // 激活组
        kieSession.getAgenda().getAgendaGroup("group-001").setFocus();

        Person person = new Person("张三", 20);
        kieSession.insert(person);

        // 只匹配规则名称是已 lock_on_active_ 开头的规则,忽略其余的规则
        kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("lock_on_active_"));
        kieSession.dispose();
    }
}

3、运行结果

lock_on_active_rule_02: 用户:[张三]当前的年龄是:[15]

可以看到只有规则二执行了,说明阻止了规则一的执行。

四、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-rule-attributes

五、参考链接

1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#rules-attributes-ref_drl-rules
2、 https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools