整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          數(shù)據(jù)庫中的定義屬性(字段)

          義屬性

          概述

          ·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ī)則屬性

          規(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ī)則屬性案例

          此處編寫出規(guī)則文件和部分核心Java代碼


          項目結(jié)構(gòu)

          1、salience

          定義規(guī)則執(zhí)行的優(yōu)先級,salience的值越大,優(yōu)先級越高

          1、規(guī)則文件的編寫

          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)存中獲取的。

          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");
          
                  // 向工作內(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)先級。

          3、運行結(jié)果

          rule 3
          rule 1
          rule 2
          

          因為 salience 的值越大優(yōu)先級越高,所以是這個順序。

          2、enabled

          定義規(guī)則是否啟用,true啟用 false禁用

          1、規(guī)則文件編寫

          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ī)則不能運行。

          2、java代碼編寫

          /**
           * 測試規(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();
              }
          }
          

          沒有需要注意的地方

          3、運行結(jié)果

          enabled_rule_2

          可以看到只有規(guī)則enabled_rule_2輸出了結(jié)果,而enabled_rule_1被禁用了。

          3、date-effective

          定義規(guī)則什么時候啟用,只有當(dāng)前時間>規(guī)則時間才會啟用。需要注意默認(rèn)的時間格式,可以通過java代碼進(jìn)行修改。

          1、規(guī)則文件編寫

          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之后被激活

          2、java代碼編寫

          /**
           * 測試規(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,不修會報錯。

          3、運行結(jié)果

          當(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)前時間不符合。

          4、注意事項

          如果出現(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")

          4、date-expires

          定義規(guī)則的過期時間,即規(guī)則到了該時間之后就不可使用了。和date-effective的用法類似,此處就不演示了。

          5、no-loop

          定義當(dāng)當(dāng)前規(guī)則的結(jié)果修改了fact對象時,是否可以再次執(zhí)行該規(guī)則。可以防止死循環(huán)

          1、規(guī)則文件編寫

          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表示如果當(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_2no-loop false表示如果當(dāng)前規(guī)則的RHS部分,對Fact對象進(jìn)行了修改,那么還會再次匹配這個規(guī)則。

          2、java代碼編寫

          /**
           * 測試規(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í)行。

          3、運行結(jié)果

          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é)果。

          6、agenda-group

          將被模式匹配成功后的規(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

          1、規(guī)則文件編寫

          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í)行的。

          2、java代碼編寫

          /**
           * 測試規(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分組。

          3、運行結(jié)果

          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í)行的。

          7、auto-focus

          設(shè)置某個agenda-group默認(rèn)獲取到焦點,和在java代碼中使用kieSession.getAgenda().getAgendaGroup("group-001").setFocus();或在drl文件中使用drools.setFocus(..)一樣。

          8、activation-group

          處于該分組中激活的規(guī)則,同一個組下,只有一個規(guī)則可以執(zhí)行,其余的會被取消執(zhí)行。但是別的組中激活的規(guī)則還是可以執(zhí)行的。

          1、規(guī)則文件編寫

          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í)行。

          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");
                  // 只匹配規(guī)則名稱是已 activation_group_ 開頭的規(guī)則,忽略其余的規(guī)則
                  kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("activation_group_"));
                  kieSession.dispose();
              }
          }
          

          3、運行結(jié)果

          activation_group_001_rule_2
          activation_group_002_rule_3
          activation_group_no_group_rule_4
          

          可以看到分組group-001中有2個規(guī)則,但是只執(zhí)行了一個規(guī)則。

          9、duration

          long類型的值,單位毫秒,如果在這個時間之后規(guī)則還成立,那么執(zhí)行該規(guī)則。

          1、規(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í)行。

          2、java代碼編寫

          /**
           * 在多少毫秒后,如果條件還成立,則觸發(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)用的。

          3、運行結(jié)果

          當(dāng)前時間:2022-05-18 14:13:36
          fire-thread: 2022-05-18 14:13:37 duration_rule_1 $i:4
          

          可以看到,延遲1s后規(guī)則執(zhí)行了。

          4、疑問

          如果我們在1s鐘之內(nèi),將規(guī)則的條件修改成不成立,那么規(guī)則還執(zhí)行嗎?答案:不執(zhí)行。

          10、lock-on-active

          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)。

          1、規(guī)則文件編寫

          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í)行的。

          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);
          
                  // 只匹配規(guī)則名稱是已 lock_on_active_ 開頭的規(guī)則,忽略其余的規(guī)則
                  kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("lock_on_active_"));
                  kieSession.dispose();
              }
          }
          

          3、運行結(jié)果

          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


          主站蜘蛛池模板: 国产精品视频分类一区| 色欲综合一区二区三区| 亚洲国产日韩一区高清在线| 中文乱码精品一区二区三区| 日韩一区二区a片免费观看| 少妇一夜三次一区二区| 麻豆视传媒一区二区三区| 国产成人精品a视频一区| 亚洲AV福利天堂一区二区三| 精品国产aⅴ无码一区二区| 蜜桃AV抽搐高潮一区二区| 久久se精品一区精品二区| 无码精品蜜桃一区二区三区WW| 99精品国产高清一区二区| 久久久久人妻一区精品| 国产精品一区电影| 无码AV天堂一区二区三区| asmr国产一区在线| 免费一区二区视频| 无码少妇一区二区浪潮av| 日韩精品一区二区三区老鸭窝| 在线视频亚洲一区| 伦精品一区二区三区视频| 亚洲乱码国产一区网址| 欧美日韩一区二区成人午夜电影| 久久精品国产一区二区 | 精品日韩一区二区| 日韩一区二区三区无码影院| 国产成人精品无码一区二区老年人 | 中文字幕日韩一区二区三区不| 伊人激情AV一区二区三区| 日韩精品一区二区三区中文3d | 亚洲一区二区免费视频| 久久99国产一区二区三区| 日韩成人无码一区二区三区| 精品国产一区二区三区久久 | 蜜臀Av午夜一区二区三区| 国产精品一区二区av不卡| 国产一区视频在线免费观看| 亚洲熟女综合一区二区三区| 亚欧色一区W666天堂|