義屬性
概述
·django根據(jù)屬性的類型確定以下信息
·當(dāng)前選擇的數(shù)據(jù)庫支持字段的類型
·渲染管理表單時使用的默認(rèn)html控件
·在管理站點最低限度的驗證
·django會為表增加自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設(shè)置某屬性為主鍵列后,則django不會再生成默認(rèn)的主鍵列
·屬性命名限制
·遵循標(biāo)識符規(guī)則
·由于django的查詢方式,不允許使用連續(xù)的下劃線
庫
·定義屬性時,需要字段類型,字段類型被定義在django.db.models.fields目錄下,為了方便使用,被導(dǎo)入到django.db.models中
·使用方式
·導(dǎo)入from django.db import models
·通過models.Field創(chuàng)建字段類型的對象,賦值給屬性
邏輯刪除
·對于重要數(shù)據(jù)都做邏輯刪除,不做物理刪除,實現(xiàn)方法是定義isDelete屬性,類型為BooleanField,默認(rèn)值為False
字段類型
·AutoField
·一個根據(jù)實際ID自動增長的IntegerField,通常不指定如果不指定,一個主鍵字段將自動添加到模型中
·CharField(max_length=字符長度)
·字符串,默認(rèn)的表單樣式是 TextInput
·TextField
·大文本字段,一般超過4000使用,默認(rèn)的表單控件是Textarea
·IntegerField
·整數(shù)
·DecimalField(max_digits=None, decimal_places=None)
·使用python的Decimal實例表示的十進(jìn)制浮點數(shù)
·參數(shù)說明
·DecimalField.max_digits
·位數(shù)總數(shù)
·DecimalField.decimal_places
·小數(shù)點后的數(shù)字位數(shù)
·FloatField
·用Python的float實例來表示的浮點數(shù)
·BooleanField
·true/false 字段,此字段的默認(rèn)表單控制是CheckboxInput
·NullBooleanField
·支持null、true、false三種值
·DateField([auto_now=False, auto_now_add=False])
·使用Python的datetime.date實例表示的日期
·參數(shù)說明
·DateField.auto_now
·每次保存對象時,自動設(shè)置該字段為當(dāng)前時間,用于"最后一次修改"的時間戳,它總是使用當(dāng)前日期,默認(rèn)為false
·DateField.auto_now_add
·當(dāng)對象第一次被創(chuàng)建時自動設(shè)置當(dāng)前時間,用于創(chuàng)建的時間戳,它總是使用當(dāng)前日期,默認(rèn)為false
·說明
·該字段默認(rèn)對應(yīng)的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日歷控件,和一個“Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵
·注意
·auto_now_add, auto_now, and default 這些設(shè)置是相互排斥的,他們之間的任何組合將會發(fā)生錯誤的結(jié)果
·TimeField
·使用Python的datetime.time實例表示的時間,參數(shù)同DateField
·DateTimeField
·使用Python的datetime.datetime實例表示的日期和時間,參數(shù)同DateField
·FileField
·一個上傳文件的字段
·ImageField
·繼承了FileField的所有屬性和方法,但對上傳的對象進(jìn)行校驗,確保它是個有效的image
字段選項
·概述
·通過字段選項,可以實現(xiàn)對字段的約束
·在字段對象時通過關(guān)鍵字參數(shù)指定
·null
·如果為True,Django 將空值以NULL 存儲到數(shù)據(jù)庫中,默認(rèn)值是 False
·blank
·如果為True,則該字段允許為空白,默認(rèn)值是 False
·注意
·null是數(shù)據(jù)庫范疇的概念,blank是表單驗證證范疇的
·db_column
·字段的名稱,如果未指定,則使用屬性的名稱
·db_index
·若值為 True, 則在表中會為此字段創(chuàng)建索引
·default
·默認(rèn)值
·primary_key
·若為 True, 則該字段會成為模型的主鍵字段
·unique
·如果為 True, 這個字段在表中必須有唯一值
關(guān)系
·分類
·ForeignKey:一對多,將字段定義在多的端中
·ManyToManyField:多對多,將字段定義在兩端中
·OneToOneField:一對一,將字段定義在任意一端中
·用一訪問多
·格式
·對象.模型類小寫_set
·示例
grade.students_set
·用一訪問一
·格式
·對象.模型類小寫
·示例
·grade.students
·訪問id
·格式
·對象.屬性_id
·示例
·student.sgrade_id
JavaScript 類型是在java.util.Date類的基礎(chǔ)上建立起來的。所以,Date類型使用的是UTC, 又稱世界統(tǒng)一時間,使用自1970年1月1日起經(jīng)過的毫秒數(shù)來保存,可以精確到之后的285616年。
//創(chuàng)建一個日期對象
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 (中國標(biāo)準(zhǔn)時間)
//IE: Wed Nov 07 21:31:23 UTC+0800 2018
//Opera: Wed Nov 07 2018 21:31:23 GMT+0800
構(gòu)造方法中可以傳遞參數(shù),指定需要的時間,如果沒有傳參數(shù),就默認(rèn)使用當(dāng)前的時間。調(diào)用Date構(gòu)造方法不傳遞參數(shù)時,新實例化的對象自動獲取當(dāng)前的日期時間,但是在不同的瀏覽器上顯示的結(jié)果是有區(qū)別的,如上所示。
ECMAScript 中有兩個方法,分別是 Date.parse() 和 Date.UTC(), 這兩個方法屬于靜態(tài)方法,不需要進(jìn)行實例化。 Date.parse()方法接收一個日期格式的參數(shù),并根據(jù)這個字符串返回相應(yīng)的毫秒數(shù)。例如:
console.log(Date.parse("4/12/2007")); //返回一個毫秒數(shù)。毫秒數(shù)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); //注意參數(shù)當(dāng)中是數(shù)字
console.log(date); //Thu Apr 12 2007 00:00:00 GMT+0800
如果參數(shù)變成字符串?dāng)?shù)字,如下:
var date = new Date("1176307200000"); //注意參數(shù)當(dāng)中是字符串
console.log(date); //Invalid Date
當(dāng)然可以這樣寫,var date = new Date("4/12/2007"); console.log(date);
//Thu Apr 12 2007 00:00:00 GMT+0800, 默認(rèn)后臺自動調(diào)用Date.parse() 方法。
關(guān)于更多日期和時間的用法,請關(guān)注下期的更新。
規(guī)則屬性是您可以添加到業(yè)務(wù)規(guī)則以修改規(guī)則行為的附加規(guī)范。 在 DRL 文件中,您通常在規(guī)則條件和操作的上方定義規(guī)則屬性,多個屬性位于單獨的行中,格式如下:
rule "rule_name"
// Attribute
// Attribute
when
// Conditions
then
// Actions
end
規(guī)則屬性 | 解釋 | 舉例 |
salience | 定義規(guī)則優(yōu)先級,是一個整數(shù)。當(dāng)在激活隊列中排序時,salience的值越大,優(yōu)先級越高。 | salience 99 |
enabled | 定義規(guī)則是否啟用. true 啟用,false 禁用,默認(rèn)值是true | enabled true |
date-effective | 包含時間和日期的字符串,當(dāng)當(dāng)前時間大于date-effective時,該規(guī)則才會被激活。這個時間格式可以修改,見下方具體的用法 | date-effective "4-5月-2022" |
date-expires | 設(shè)置規(guī)則的過期時間,時間格式和上方一樣。 | date-expires "4-5月-2022" |
no-loop | 布爾值,默認(rèn)值為false, 定義當(dāng)當(dāng)前規(guī)則規(guī)則的結(jié)果修改了fact對象時,是否可以再次執(zhí)行該規(guī)則。true:不可以, false:可以,可能會導(dǎo)致死循環(huán)。指的是當(dāng)前規(guī)則的修改,如果別的規(guī)則修改了,還會導(dǎo)致該規(guī)則的觸發(fā) | no-loop true |
agenda-group | Agenda groups允許您對agenda進(jìn)行分區(qū),以提供對規(guī)則組的更多執(zhí)行控制。 只有獲得焦點的議程組中的規(guī)則才能被激活。 ,但是這個里面有個特例,如果某個規(guī)則沒有配置 agenda-group,但是它模式匹配成功了,那么會被分到默認(rèn)的組(main),這個main組的規(guī)則也會執(zhí)行。 | agenda-group "GroupName" |
auto-focus | 布爾值,僅適用于Agenda-Group內(nèi)的規(guī)則。當(dāng)值為true時,下次激活該規(guī)則時,會將焦點自動給這個Agenda group | auto-focus true |
activation-group | 表示該組下的規(guī)則只有一個規(guī)則會被執(zhí)行,該組下其余激活的規(guī)則會被取消執(zhí)行。 但是別的組激活的規(guī)則可能會被執(zhí)行。 | activation-group "GroupName" |
duration | long類型的值,如果在這個時間之后規(guī)則還成立,那么執(zhí)行該規(guī)則 | duration 1000 |
timer | 一個字符串,標(biāo)識用于調(diào)度規(guī)則的 int(間隔)或 cron 計時器定義。 | Example: timer ( cron:* 0/15 * * * ? ) (every 15 minutes) |
calendar | 定義Quartz calendar用于調(diào)度規(guī)則。 | |
lock-on-active | 一個布爾值,僅適用于規(guī)則流組或議程組中的規(guī)則。 選擇該選項后,下次規(guī)則的規(guī)則流組變?yōu)榛顒訝顟B(tài)或規(guī)則的議程組獲得焦點時,規(guī)則無法再次激活,直到規(guī)則流組不再處于活動狀態(tài)或議程組失去焦點。 這是 no-loop 屬性的更強(qiáng)版本,因為匹配規(guī)則的激活被丟棄,無論更新的來源如何(不僅是規(guī)則本身)。 此屬性非常適合計算規(guī)則,其中您有許多修改事實的規(guī)則并且您不希望任何規(guī)則重新匹配和再次觸發(fā)。 | lock-on-active true |
dialect | 將 JAVA 或 MVEL 標(biāo)識為用于規(guī)則中的代碼表達(dá)式的語言的字符串。 默認(rèn)情況下,該規(guī)則使用在包級別指定的方言。 此處指定的任何方言都會覆蓋該規(guī)則的包方言設(shè)置。 | dialect "JAVA" |
此處編寫出規(guī)則文件和部分核心Java代碼
項目結(jié)構(gòu)
定義規(guī)則執(zhí)行的優(yōu)先級,salience的值越大,優(yōu)先級越高
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
// 此處優(yōu)先級的值是動態(tài)獲取來的
rule "salience_rule_3"
salience $dynamicSalience
when
$dynamicSalience: Integer()
then
System.out.println("rule 3");
end
注意:
我們的salience_rule_3的優(yōu)先級的值是動態(tài)來的,即是從工作內(nèi)存中獲取的。
public class DroolsSalienceApplication {
public static void main(String[] args) {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
// 向工作內(nèi)存中插入一個Integer值,salience_rule_3 需要用到這個優(yōu)先級
kieSession.insert(10);
// 只匹配規(guī)則名稱是已 salience_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("salience_"));
kieSession.dispose();
}
}
kieSession.insert(10);此處向工作內(nèi)存中插入一個值,將會匹配到salience_rule_3,然后動態(tài)修改它的優(yōu)先級。
rule 3
rule 1
rule 2
因為 salience 的值越大優(yōu)先級越高,所以是這個順序。
定義規(guī)則是否啟用,true啟用 false禁用
package rules
rule "enabled_rule_1"
// 禁用此規(guī)則
enabled false
when
then
System.out.println("enabled_rule_1");
end
rule "enabled_rule_2"
// 啟用此規(guī)則,默認(rèn)就是啟用
enabled true
when
then
System.out.println("enabled_rule_2");
end
enabled_rule_2這個規(guī)則需要運行,enabled_rule_1這個規(guī)則不能運行。
/**
* 測試規(guī)則的啟用和禁用
*/
public class DroolsEnabledApplication {
public static void main(String[] args) {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
// 只匹配規(guī)則名稱是已 enabled_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("enabled_"));
kieSession.dispose();
}
}
沒有需要注意的地方
enabled_rule_2
可以看到只有規(guī)則enabled_rule_2輸出了結(jié)果,而enabled_rule_1被禁用了。
定義規(guī)則什么時候啟用,只有當(dāng)前時間>規(guī)則時間才會啟用。需要注意默認(rèn)的時間格式,可以通過java代碼進(jìn)行修改。
package rules
import java.text.SimpleDateFormat
import java.util.Date
// 規(guī)則一:輸出當(dāng)前時間
rule "date_effective_rule_1"
when
then
System.out.println("當(dāng)前時間:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
// 規(guī)則二: 該規(guī)則會在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執(zhí)行了,規(guī)則允許被執(zhí)行的時間應(yīng)該在2022-05-18 10:54:26之后");
end
// 規(guī)則三: 該規(guī)則會在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
規(guī)則一:輸出當(dāng)前時間
規(guī)則二: 該規(guī)則會在2022-05-18 10:54:26之后被激活
規(guī)則三: 該規(guī)則會在2023-05-18 10:54:26之后被激活
/**
* 測試規(guī)則在執(zhí)行的時間之后才能執(zhí)行
*/
public class DroolsDateEffectiveApplication {
public static void main(String[] args) {
// 設(shè)置日期格式,否則可能會報錯(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");
// 只匹配規(guī)則名稱是已 date_effective_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("date_effective_"));
kieSession.dispose();
}
}
需要注意System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");這句,這個修改drools中的日期格式,因為規(guī)則中寫的日期格式為date-effective "2023-05-18 10:54:26"而默認(rèn)的格式為d-MMM-yyyy,不修會報錯。
當(dāng)前時間:2022-05-18 10:59:38
date_effective_rule_2執(zhí)行了,規(guī)則允許被執(zhí)行的時間應(yīng)該在2022-05-18 10:54:26之后
可以看到規(guī)則二執(zhí)行了,規(guī)則三沒有執(zhí)行,因為規(guī)則三需要時間到達(dá)了2023-05-18 10:54:26才執(zhí)行,而當(dāng)前時間不符合。
如果出現(xiàn)了Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]]這個錯誤該怎么解決了,這是因為日期格式不正確。需要在java代碼中進(jìn)行如下設(shè)置System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss")
定義規(guī)則的過期時間,即規(guī)則到了該時間之后就不可使用了。和date-effective的用法類似,此處就不演示了。
定義當(dāng)當(dāng)前規(guī)則的結(jié)果修改了fact對象時,是否可以再次執(zhí)行該規(guī)則。可以防止死循環(huán)
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_1:no-loop true表示如果當(dāng)前規(guī)則的RHS部分,對Fact對象進(jìn)行了修改,則不會再次觸發(fā)該規(guī)則。那如果是no_loop_rule_2修改了,會導(dǎo)致該規(guī)則的觸發(fā)嗎?答案是會觸發(fā),如果我不想被觸發(fā)呢?那么使用lock-on-active可以實現(xiàn)。
no_loop_rule_2:no-loop false表示如果當(dāng)前規(guī)則的RHS部分,對Fact對象進(jìn)行了修改,那么還會再次匹配這個規(guī)則。
/**
* 測試規(guī)則是否可以再次被執(zhí)行
*/
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);
// 只匹配規(guī)則名稱是已 no_loop_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("no_loop_"));
// 睡眠5s,使規(guī)則文件中的規(guī)則執(zhí)行完
TimeUnit.SECONDS.sleep(5);
kieSession.dispose();
}
}
此處 java 代碼,睡眠了5s,是為了讓規(guī)則執(zhí)行。
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被觸發(fā),由于RHS部分使用了modify修改了規(guī)則內(nèi)存中的對象,但是該規(guī)則存在 no-loop true 的屬性,所以該規(guī)則沒有再次被觸發(fā),即只輸出了一次。
2022-05-18 11:42:30 no_loop_rule_2 i=10 2022-05-18 11:42:30 no_loop_rule_1 i=10 此時規(guī)則 no_loop_rule_2 執(zhí)行了,由于該規(guī)則的 no-loop 為 false 并且使用了 modify 方法,所以該規(guī)則多次被觸發(fā)了,從結(jié)果上看,貌似規(guī)則 no_loop_rule_1 又再次被觸發(fā)了,不是應(yīng)該不被觸發(fā)嗎,因為設(shè)置了no-loop true?因為這是no_loop_rule_2導(dǎo)致no_loop_rule_1觸發(fā)的,而no_loop只對自身的RHS修改有效。
疑問:
那如果將 no-loop換成lock-on-active結(jié)果會一樣嗎?可以自己嘗試一下看看結(jié)果。
將被模式匹配成功后的規(guī)則,進(jìn)行分組,只有獲得焦點的組,才可以執(zhí)行規(guī)則。但是這個里面有個特列,如果某個規(guī)則在模式匹配,匹配成功了,但是沒有配置agenda-group,那么它會被分配到main組,這個main組的規(guī)則總是執(zhí)行的。
agenda-group的數(shù)據(jù)結(jié)構(gòu)就類似stack,激活的組是在棧頂。參考如下圖:
agenda-group
參考鏈接: https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools
package rules
/**
agenda-group 的數(shù)據(jù)結(jié)構(gòu)類似與棧,激活的組會被放置在棧頂,
`main`是默認(rèn)組,總是存在的,即沒有配置agenda-group的就是`main`,
`main`總是會執(zhí)行的。
*/
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總是會被執(zhí)行的。
/**
* 測試規(guī)則分組
*/
public class DroolsAgendaGroupApplication {
public static void main(String[] args) {
// 設(shè)置日期格式,否則可能會報錯(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();
// 只匹配規(guī)則名稱是已 agenda_group_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("agenda_group_"));
kieSession.dispose();
}
}
激活group-001分組。
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分組,它不應(yīng)該輸出啊。這是應(yīng)為這個規(guī)則模式匹配成功后被分配到了默認(rèn)的main組,而main組一定會被執(zhí)行的。
設(shè)置某個agenda-group默認(rèn)獲取到焦點,和在java代碼中使用kieSession.getAgenda().getAgendaGroup("group-001").setFocus();或在drl文件中使用drools.setFocus(..)一樣。
處于該分組中激活的規(guī)則,同一個組下,只有一個規(guī)則可以執(zhí)行,其余的會被取消執(zhí)行。但是別的組中激活的規(guī)則還是可以執(zhí)行的。
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"此處對這個組的規(guī)則指定了優(yōu)先級,優(yōu)先級高的先執(zhí)行,執(zhí)行完之后,該組別的規(guī)則不執(zhí)行。
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");
// 只匹配規(guī)則名稱是已 activation_group_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("activation_group_"));
kieSession.dispose();
}
}
activation_group_001_rule_2
activation_group_002_rule_3
activation_group_no_group_rule_4
可以看到分組group-001中有2個規(guī)則,但是只執(zhí)行了一個規(guī)則。
long類型的值,單位毫秒,如果在這個時間之后規(guī)則還成立,那么執(zhí)行該規(guī)則。
package rules
import java.text.SimpleDateFormat
import java.util.Date
rule "duration_rule_1"
// 延遲1s后執(zhí)行規(guī)則
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
定義規(guī)則延遲1s后進(jìn)行執(zhí)行。
/**
* 在多少毫秒后,如果條件還成立,則觸發(fā)該規(guī)則
*/
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);
// 只匹配規(guī)則名稱是已 duration_ 開頭的規(guī)則,忽略其余的規(guī)則
new Thread(() -> {
// 調(diào)用此方法會阻塞調(diào)用線程,直到 `kieSession.halt();`的調(diào)用
System.out.println("當(dāng)前時間:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
kieSession.fireUntilHalt(new RuleNameStartsWithAgendaFilter("duration_"));
}, "fire-thread").start();
// 如果修改這個值,使得規(guī)則的條件不成立,看規(guī)則是否還執(zhí)行
kieSession.update(factHandle, 4);
TimeUnit.SECONDS.sleep(2);
kieSession.halt();
kieSession.dispose();
}
}
注意:
1、我們調(diào)用出發(fā)所有規(guī)則執(zhí)行的方法不在是fireAllRules而是fireUntilHalt。
2、fireUntilHalt的調(diào)用會阻塞線程,直到調(diào)用halt方法,因此fireUntilHalt需要放置到另外的線程中調(diào)用。而且我們觀察規(guī)則的執(zhí)行,也是在這個線程中調(diào)用的。
當(dāng)前時間:2022-05-18 14:13:36
fire-thread: 2022-05-18 14:13:37 duration_rule_1 $i:4
可以看到,延遲1s后規(guī)則執(zhí)行了。
如果我們在1s鐘之內(nèi),將規(guī)則的條件修改成不成立,那么規(guī)則還執(zhí)行嗎?答案:不執(zhí)行。
和rule flow groups or agenda groups配合使用。
需求:
我們有2個規(guī)則,并且同屬于一個組,規(guī)則二執(zhí)行完之后,工作內(nèi)存中的Fact對象的值發(fā)生了變化,導(dǎo)致規(guī)則一滿足執(zhí)行的條件,而規(guī)則一已經(jīng)執(zhí)行一遍了,此處需要阻止規(guī)則二的觸發(fā)導(dǎo)致規(guī)則一的出觸發(fā)。使用lock-on-active 即可實現(xiàn)。
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() + "]當(dāng)前的年齡是:[" + $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() + "]當(dāng)前的年齡是:[" + $p.getAge() + "]");
end
規(guī)則lock_on_active_rule_01加了lock-on-active true屬性后,規(guī)則lock_on_active_rule_02修改Fact導(dǎo)致規(guī)則lock_on_active_rule_01的條件成立,此時規(guī)則也是不會執(zhí)行的。
/**
* 一個簡單的實體類
*
* @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);
// 只匹配規(guī)則名稱是已 lock_on_active_ 開頭的規(guī)則,忽略其余的規(guī)則
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("lock_on_active_"));
kieSession.dispose();
}
}
lock_on_active_rule_02: 用戶:[張三]當(dāng)前的年齡是:[15]
可以看到只有規(guī)則二執(zhí)行了,說明阻止了規(guī)則一的執(zhí)行。
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
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。