guangnian0412's BLOG

          Java in my life

          常用鏈接

          統(tǒng)計(jì)

          積分與排名

          我關(guān)注的Blog

          最新評論

          JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上)

          從今天開始,我們將分兩期來詳細(xì)的介紹Drools規(guī)則引擎的原理,和各關(guān)鍵類的使用方法。

          Drools 規(guī)則引擎(上)

          1. 概述 :
          Drools 分為兩個(gè)主要部分:構(gòu)建( Authoring )和運(yùn)行時(shí)( Runtime )。

          構(gòu)建的過程涉及到 .drl .xml 規(guī)則文件的創(chuàng)建,它們被讀入一個(gè)解析器,使用 ANTLR 3 語法進(jìn)行解析。解析器對語法進(jìn)行正確性的檢查,然后產(chǎn)生一種中間結(jié)構(gòu)“ descr ”, descr AST 來描述規(guī)則。 AST 然后被傳到 PackageBuilder ,由 PackagBuilder 來產(chǎn)生 Packaged 對象。 PackageBuilder 還承擔(dān)著一些代碼產(chǎn)生和編譯的工作,這些對于產(chǎn)生 Package 對象都時(shí)必需的。 Package
          對象是一個(gè)可以配置的,可序列化的,由一個(gè)或多個(gè)規(guī)則組成的對象。下圖闡明了上述過程:
          ?
          Figure 1.1
          Authoring Components

          RuleBase 是一個(gè)運(yùn)行時(shí)組件,它包含了一個(gè)或多個(gè) Package 對象??梢栽谌魏螘r(shí)刻將一個(gè) Package 對象加入或移出 RuleBase 對象。一個(gè) RuleBase 對象可以在任意時(shí)刻實(shí)例化一個(gè)或多個(gè) WorkingMemory 對象,在它的內(nèi)部保持對這些 WorkingMemory 的弱引用。 WorkingMemory 由一系列子組件組成。當(dāng)應(yīng)用程序中的對象被 assert 進(jìn) WorkingMemory ,可能會導(dǎo)致一個(gè)或多個(gè) Activation 的產(chǎn)生,然后由 Agenda 負(fù)責(zé)安排這些 Activation 的執(zhí)行。下圖說明了上述過程:

          ?
          Figure 1.2 .?Runtime Components

          2.構(gòu)建(Authoring):

          主要有三個(gè)類用來完成構(gòu)建過程:DrlParser, XmlParser PackageBuilder。兩個(gè)解析器類從傳入的Reader實(shí)例產(chǎn)生descr AST模型。PackageBuilder提供了簡便的API,使你可以忽略那兩個(gè)類的存在。這兩個(gè)簡單的方法是:“addPackageFromDrl”和“addPackageFromXml”,兩個(gè)都只要傳入一個(gè)Reader實(shí)例作為參數(shù)。下面的例子說明了如何從classpath中的xmldrl文件創(chuàng)建一個(gè)Package對象。注意:所有傳入同一個(gè)PackageBuilder實(shí)例的規(guī)則源,都必須是在相同的package 命名空間(namespace)中。

          PackageBuilder?builder?=?new?PackageBuilder();
          builder.addPackageFromDrl(?
          new?InputStreamReader(?getClass().getResourceAsStream(?"package1.drl"?)?)?);
          builder.addPackageFromXml(?
          new?InputStreamReader(?getClass().getResourceAsStream(?"package2.drl"?)?)?);
          Package?pkg?
          =?builder.getPackage();


          Figure 2.1 PackageBuilder

          PackageBuilder是可以配置的,使用PackageBuilderConfiguration。通常,你可以指定另一個(gè)parent ClassLoader和用什么編譯器(compiler),默認(rèn)是Eclipse JDT。下面顯示了如何指定JANINO編譯器:

          PackageBuilderConfiguration?conf?=?new?PackageBuilderConfiguration();
          conf.setCompiler(?PackageBuilderConfiguration.JANINO?);
          PackageBuilder?builder?
          =?new?PackageBuilder(?conf?);

          Figure 2.2 .?PackageBuilderConfiguration

          3
          RuleBase:

          Figure 3.1 .?RuleBase

          一個(gè)RuleBase包含了多個(gè)將被使用的規(guī)則包(packages of rules)。一個(gè)RuleBase是可以序列化的,所以它可以被配置到JNDI或其他類似的服務(wù)。通常,第一次使用時(shí),一個(gè)RuleBase被創(chuàng)建并緩存。RuleBaseRuleBaseFactory來實(shí)例化,默認(rèn)返回一個(gè)ReteOO RuleBase。可以傳入?yún)?shù)來指定采用ReteOOLeaps。然后,用addPackage方法加入Package實(shí)例。你可以加入有相同命名空間(namespace)的多個(gè)Package。

          RuleBase?ruleBase??=?RuleBaseFactory.newRuleBase();
          ruleBase.addPackage(pkg);

          Figure 3.2. RuleBaseFactory

          一個(gè) rulebase instance 是線程安全的,所有你可以在你的應(yīng)用中,讓一個(gè) rulebase instance 在多個(gè)線程中共享。對于一個(gè) rulebase 的最通常的操作是產(chǎn)生一個(gè)新的 WorkingMemory 。

          這個(gè) rulebase 保持著到它所產(chǎn)生的 WorkingMemoryd 的弱引用,所以在長時(shí)間運(yùn)行的 WorkingMemory 中,如果 rules 發(fā)生改變,這些 WorkingMemory 可以即使的根據(jù)最新的 rules 進(jìn)行更新,而不必重啟 WorkingMemory 。你也可以指定 RuleBase 不必保持一個(gè)弱引用,但是你要保證 RuleBase 不用更新。

          ruleBase.newWorkingMemory();?? // ?maintains?a?weak?reference.
          ruleBase.newWorkingMemory(? false ?);? // ?do?not?maintain?a?weak?reference

          任何時(shí)候, Package 可以被加入或移除;所有的改變都會被反映到現(xiàn)存的 WorkingMemory 中。不要忘了調(diào)用 fireAllRules() Activations 激發(fā)。

          ruleBase.addPackage(?pkg??);?? // ?Add?a?package?instance
          ruleBase.removePackage(? " org.com.sample " ??);?? // ?remove?a?package,?and?all?its?parts, by?it's?namespace
          ruleBase.removeRule(? " org.com.sample " ,? " my?rule " ?);? // ?remove?a?specific?rule?from?a namespace

          雖然有刪除一個(gè)單獨(dú)規(guī)則的方法,但是卻沒有加入一個(gè)單獨(dú)規(guī)則的方法(要達(dá)到這個(gè)目的只有加入一個(gè)只有一條規(guī)則的 package )。

          RuleBaseConfigurator 可以指定 RuleBase 的附加行為。在加入 RuleBase 后, RuleBaseConfiguration 就變成不可變對象。

          RuleBaseConfiguration?conf? = ? new ?RuleBaseConfiguration();

          conf.setProperty(?RuleBaseConfiguration.PROPERTY_ASSERT_BEHAVIOR,
          ??????????????????RuleBaseConfiguration.WM_BEHAVIOR_EQUALITY?);

          RuleBase?ruleBase?
          = ? new ?ReteooRuleBase(?conf?);

          兩個(gè)主要的屬性是: PROPERT_ASSERT_BEHAVIOR PROPERTY_LOGICAL_OVERRIDE_BEHAVIOR (在以后的部分中會解釋)。所有的屬性值都是 RuleBaseConfiguration 類中的靜態(tài)域常量。


          Figure 3.3 RuleBaseConfiguration



          posted on 2006-06-04 12:50 guangnian 閱讀(22505) 評論(14)  編輯  收藏 所屬分類: JBoss Rules(Drools)

          評論

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2006-06-08 00:02 steeven

          好文,謝謝~

          偶一直在想什么場合下需要rule engine.
          1. 如果邏輯在開發(fā)前就定好,雖然比較復(fù)雜,如果用rule engine,碰到重構(gòu),rule要手工操作。而且規(guī)則語法的錯誤不容易檢查出來。
          2. 如果要客戶來寫規(guī)則,讓客戶學(xué)習(xí)語法規(guī)則還是用界面生成呢?
            回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2006-06-08 15:00 guangnian

          @steeven
          我想rule engine主要用在規(guī)則經(jīng)常變化的情況在,此時(shí)只需要改動drl文件,而不需要改代碼。對于規(guī)則語法錯誤可以靠IDE工具來寫規(guī)則啊,JBoss已經(jīng)有提供Eclipse plugin了。
          規(guī)則當(dāng)然是程序員根據(jù)客戶的需求來寫的啊  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2006-11-22 18:09 syyhpf

          那測試呢?修改完規(guī)則后怎樣測試?在運(yùn)行系統(tǒng)中?  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2006-11-30 14:55 coolfish

          應(yīng)該有專門的測試環(huán)境吧  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2007-07-04 13:30 liujg

          所有傳入同一個(gè)PackageBuilder實(shí)例的規(guī)則源,都必須是在相同的package 命名空間(namespace)中.請問這里的package的命名空間是什么呢?  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2007-07-04 13:38 liujg

          看來今年沒有人關(guān)注該貼了!郁悶......  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上)[未登錄] 2007-08-23 12:48 dd

          好文章啊,要是能給個(gè)具體的操作就好了..舉個(gè)例子就好了.我看的很迷糊  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上)[未登錄] 2007-08-27 09:29 sclsch

          mark  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2007-11-24 15:32 myim

          我給個(gè)例子:
          電梯行業(yè),

          如果樓層高是10層
          那么控制板上的按鈕就是10+5(其它功能)個(gè)
          如果載重1000公斤
          那么就選擇A型號的電機(jī)
          如果是前后開門
          那么加工路線就是R
          如果門是對開
          那么就選擇Item Number D作為這個(gè)合同的門類型來加工
          如果客戶要噴涂藍(lán)色的門
          那么就選擇噴涂加工路線,
          并且噴涂顏料選擇Item Number Blue
          。。。。

          類似的Rule可以達(dá)到幾萬條以上,不知道這個(gè)企業(yè)作用是否適合選擇DRools來做,真實(shí)地ERP中也使用Rule來做的。

          請問DRools在這樣的場景中是否物有所值?還是說DRools用在這樣的地方,大材小用了,他有更高級的用處?

          剛剛發(fā)現(xiàn)DRools, 非常有興趣研究
            回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2008-01-18 14:16 ePim

          路過,今天開始接觸這個(gè)東本,好難入門啊~~  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2009-02-10 15:16 hc

          這個(gè)版本低了 很多屬性字段都不適用了   回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上) 2010-02-03 17:30 ddoo

          http://www.jboss.org/drools/documentation.html

          這上面有更詳細(xì)的文檔.  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上)[未登錄] 2011-03-05 23:01 xiaogang

          請問文中所說的 descr AST中間結(jié)構(gòu)是一種什么樣的結(jié)構(gòu)啊?在網(wǎng)上搜不到相關(guān)資料,謝謝  回復(fù)  更多評論   

          # re: JBoss Rules 學(xué)習(xí)(三): Drools規(guī)則引擎 (上)[未登錄] 2014-03-21 14:19 Lee

          也就是說我可以用antlr把自己的規(guī)則語法映射到drools可是別的程度 so good  回復(fù)  更多評論   

          主站蜘蛛池模板: 西华县| 慈溪市| 兖州市| 克东县| 荣昌县| 清镇市| 获嘉县| 营山县| 龙江县| 同心县| 菏泽市| 拜泉县| 渝北区| 屏南县| 乃东县| 通州市| 江达县| 榆社县| 鹤山市| 广河县| 龙岩市| 璧山县| 收藏| 龙海市| 南澳县| 泽库县| 疏勒县| 阜新市| 建德市| 北宁市| 牙克石市| 江阴市| 永春县| 嘉鱼县| 诏安县| 阿拉善左旗| 龙门县| 康平县| 沭阳县| 祁连县| 阜阳市|