Drools 規則引擎(上)

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

Drools 規則引擎(上)

1. 概述 :
Drools 分爲兩個主要部分:構建( Authoring )和運行時( Runtime )。

構建的過程涉及到 .drl 或 .xml 規則文件的創建,它們被讀入一個解析器,使用 ANTLR 3 語法進行解析。解析器對語法進行正確性的檢查,然後產生一種中間結構“ descr ”, descr 用 AST 來描述規則。 AST 然後被傳到 PackageBuilder ,由 PackagBuilder 來產生 Packaged 對象。 PackageBuilder 還承擔着一些代碼產生和編譯的工作,這些對於產生 Package 對象都時必需的。 Package 
對象是一個可以配置的,可序列化的,由一個或多個規則組成的對象。下圖闡明瞭上述過程: 
  
Figure 1.1 Authoring Components

RuleBase 是一個運行時組件,它包含了一個或多個 Package 對象。可以在任何時刻將一個 Package 對象加入或移出 RuleBase 對象。一個 RuleBase 對象可以在任意時刻實例化一個或多個 WorkingMemory 對象,在它的內部保持對這些 WorkingMemory 的弱引用。 WorkingMemory 由一系列子組件組成。當應用程序中的對象被 assert 進 WorkingMemory ,可能會導致一個或多個 Activation的產生,然後由 Agenda 負責安排這些 Activation 的執行。下圖說明了上述過程:

  
Figure 1.2 . Runtime Components

2.構建(Authoring):

主要有三個類用來完成構建過程:DrlParser, XmlParser 和 PackageBuilder。兩個解析器類從傳入的Reader實例產生descr AST模型。PackageBuilder提供了簡便的API,使你可以忽略那兩個類的存在。這兩個簡單的方法是:“addPackageFromDrl”和“addPackageFromXml”,兩個都只要傳入一個Reader實例作爲參數。下面的例子說明了如何從classpath中的xml和drl文件創建一個Package對象。注意:所有傳入同一個PackageBuilder實例的規則源,都必須是在相同的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。通常,你可以指定另一個parent ClassLoader和用什麼編譯器(compiler),默認是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

一個RuleBase包含了多個將被使用的規則包(packages of rules)。一個RuleBase是可以序列化的,所以它可以被配置到JNDI或其他類似的服務。通常,第一次使用時,一個RuleBase被創建並緩存。RuleBase用RuleBaseFactory來實例化,默認返回一個ReteOO RuleBase。可以傳入參數來指定採用ReteOO或Leaps。然後,用addPackage方法加入Package實例。你可以加入有相同命名空間(namespace)的多個Package。

RuleBase ruleBase  = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
 
Figure 3.2. RuleBaseFactory

一個 rulebase instance 是線程安全的,所有你可以在你的應用中,讓一個 rulebase instance 在多個線程中共享。對於一個 rulebase 的最通常的操作是產生一個新的 WorkingMemory 。

這個 rulebase 保持着到它所產生的 WorkingMemoryd 的弱引用,所以在長時間運行的 WorkingMemory 中,如果 rules 發生改變,這些WorkingMemory 可以即使的根據最新的 rules 進行更新,而不必重啓 WorkingMemory 。你也可以指定 RuleBase 不必保持一個弱引用,但是你要保證RuleBase 不用更新。

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

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

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

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

<!--[if !supportEmptyParas]-->

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

RuleBaseConfiguration conf  =   new  RuleBaseConfiguration();

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

RuleBase ruleBase  =   new  ReteooRuleBase( conf );

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

 
Figure 3.3 RuleBaseConfiguration 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章