Java規則引擎與其API應用詳解

來源:互聯網
上載者:User
詳解

  本文對Java規則引擎與其API(JSR-94)及相關實現做了較詳細的介紹,對其體繫結構和API應用有較詳盡的描述,並指出Java規則引擎,規則語言,JSR-94的相互關係,以及JSR-94的不足之處和展望

  本文對Java規則引擎與其API(JSR-94)及相關實現做了較詳細的介紹,對其體繫結構和API應用有較詳盡的描述,並指出Java規則引擎,規則語言,JSR-94的相互關係,以及JSR-94的不足之處和展望

  複雜企業階層專案的開發以及其中隨外部條件不斷變化的商務規則(business logic),迫切需要分離商業決策者的商業決策邏輯和應用開發人員的技術決策,並把這些商業決策放在中樞資料庫或其他統一的地方,讓它們能在運行時(即商務時間)可以動態地管理和修改從而提供軟體系統的柔性和適應性。規則引擎正是應用於上述動態環境中的一種解決方案。

  本文第一部分簡要介紹了規則引擎的產生背景和基於規則的專家系統,第二部分介紹了什麼是規則引擎及其架構和演算法,第三部分介紹了商業產品和開源項目實現等各種Java規則引擎,第四部分對Java規則引擎API(JSR-94)作了詳細介紹,講解了其體繫結構,管理API和運行時API及相關安全問題,第五部分則對規則語言及其標準化作了探討,第六部分給出了一個使用Java規則引擎API的簡單樣本,第七部分給予小結和展望。

  1、 介紹

  1.1 規則引擎產生背景

  企業管理者對企業級IT系統的開發有著如下的要求:(1)為提高效率,管理流程必須自動化,即使現代商業規則異常複雜(2)市場要求商務規則經常變化,IT系統必須依據商務規則的變化快速、低成本的更新(3)為了快速、低成本的更新,業務人員應能直接管理IT系統中的規則,不需要程式開發人員參與。

  而項目開發人員則碰到了以下問題:(1)程式=演算法+資料結構,有些複雜的商業規則很難推匯出演算法和抽象出資料模型(2)軟體工程要求從需求->設計->編碼,然而商務規則常常在需求階段可能還沒有明確,在設計和編碼後還在變化,商務規則往往嵌在系統各處代碼中(3)對程式員來說,系統已經維護、更新困難,更不可能讓業務人員來管理。

  基於規則的專家系統的出現給開發人員以解決問題的契機。規則引擎由基於規則的專家系統中的推理引擎發展而來。下面簡要介紹一下基於規則的專家系統。

  1.2 基於規則的專家系統(RBES)

  專家系統是人工智慧的一個分支,它模仿人類的推理方式,使用試探性的方法進行推理,並使用人類能理解的術語解釋和證明它的推理結論。專家系統有很多分類:神經網路、基於案例推理和基於規則系統等。

  RBES包括三部分:Rule Base(knowledge base)、Working Memory(fact base)和Inference Engine(推理引擎)。它們的結構如下所示:

圖1.基於規則的專家系統組成

  如上圖所示,推理引擎包括三部分:Pattern Matcher、Agenda和Execution Engine。Pattern Matcher何時執行哪個規則;Agenda管理PatternMatcher挑選出來的規則的執行次序;Execution Engine負責執行規則和其他動作。

  推理引擎通過決定哪些規則滿足事實或目標,並授予規則優先順序,滿足事實或目標的規則被加入議程。存在兩者推理方式:演繹法(Forward-Chaining正向鏈)和歸納法(Backward-Chaining反向鏈)。演繹法從一個初始的事實出發,不斷地應用規則得出結論(或執行指定的動作)。而歸納法則是從假設出發,不斷地尋找符合假設的事實。

  2、 規則引擎

  2.1 商務規則
 
  一個商務規則包含一組條件和在此條件下執行的操作,它們表示商務規則應用程式的一段商務邏輯。商務規則通常應該由業務分析人員和策略管理者開發和修改,但有些複雜的商務規則也可以由技術人員使用物件導向的技術語言或指令碼來定製。商務規則的理論基礎是:設定一個或多個條件,當滿足這些條件時會觸發一個或多個操作。

  2.2 規則引擎

  什麼是規則引擎?規則引擎是如何執行規則的?這可以稱之為"什麼"與"如何"的問題。到底規則引擎是什麼還是目前業界一個比較有爭議的問題,在JSR-94種也幾乎沒有定義。可以這樣認為充分定義和解決了"如何"的問題,"什麼"問題本質上也迎刃而解。也許這又是一種"先有蛋還是先有雞"哲學爭論。今後標準規則語言的定義和推出及相關標準的制定應該可以給這樣的問題和爭論划上一個句號。本文中,暫且這樣述說什麼是規則引擎:規則引擎由推理引擎發展而來,是一種嵌入在應用程式中的組件,實現了將業務決策從應用程式代碼中分離出來,並使用預定義的語義模組編寫業務決策。接受資料輸入,解釋商務規則,並根據規則做出業務決策。

  2.3 規則引擎的使用方式

  由於規則引擎是軟體組件,所以只有開發人員才能夠通過程式介面的方式來使用和控制它,規則引擎的程式介面至少包含以下幾種API:載入和卸載規則集的API;資料操作的API;引擎執行的API。開發人員在程式中使用規則引擎基本遵循以下5個典型的步驟:建立規則引擎對象;向引擎中載入規則集或更換規則集;向引擎提交需要被規則集處理的資料對象集合;命令引擎執行;匯出引擎執行結果,從引擎中撤出處理過的資料。使用了規則引擎之後,許多涉及商務邏輯的程式碼基本被這五個典型步驟所取代。

  一個開放的商務規則引擎應該可以"嵌入"在應用程式的任何位置,不同位置的規則引擎可以使用不同的規則集,用於處理不同的資料對象。此外,對使用引擎的數量沒有限制。

  2.4 規則引擎架構與推理

  規則引擎的架構如下圖所示:

圖2. 商務規則引擎架構

  規則引擎的推理步驟如下:a. 將初始資料(fact)輸入至工作記憶體(Working Memory)。b. 使用Pattern Matcher將規則庫(Rules repository)中的規則(rule)和資料(fact)比較。c. 如果執行規則存在衝突(conflict),即同時啟用了多個規則,將衝突的規則放入衝突集合。d. 解決衝突,將啟用的規則按順序放入Agenda。e. 執行Agenda中的規則。重複步驟b至e,直到執行完畢Agenda中的所有規則。

  任何一個規則引擎都需要很好地解決規則的推理機制和規則條件匹配的效率問題。

  當引擎執行時,會根據規則執行隊列中的優先順序逐條執行規則執行執行個體,由於規則的執行部分可能會改變工作區的資料對象,從而會使隊列中的某些規則執行執行個體因為條件改變而失效,必須從隊列中撤銷,也可能會啟用原來不滿足條件的規則,產生新的規則執行執行個體進入隊列。於是就產生了一種"動態"的規則執行鏈,形成規則的推理機制。這種規則的"鏈式"反應完全是由工作區中的資料驅動的。

  規則條件匹配的效率決定了引擎的效能,引擎需要迅速測試工作區中的資料對象,從載入的規則集中發現合格規則,建置規則執行執行個體。1982年美國卡耐基·梅隆大學的Charles L. Forgy發明了一種叫Rete演算法,很好地解決了這方面的問題。目前世界頂尖的商用商務規則引擎產品基本上都使用Rete演算法。

  2.5 規則引擎的演算法
 
  大部分規則引擎產品的演算法,基本上都來自於Dr. Charles Forgy在1979年提出的RETE演算法及其變體,Rete演算法是目前效率最高的一個Forward-Chaining推理演算法,Drools項目是Rete演算法的一個物件導向的Java實現,Rete演算法其核心思想是將分離的匹配項根據內容動態構造匹配樹,以達到顯著降低計算量的效果。

  3、 Java規則引擎
 
  目前主流的規則引擎組件多是基於Java和C++程式語言環境,已經有多種Java規則引擎商業產品與開源項目的實現,其中有的已經支援JSR94,有的正朝這個方向做出努力,列出如下:

  3.1 Java規則引擎商業產品

  Java規則引擎商業產品主要有(Jess不是開源項目,它可以免費用於學術研究,但用於商業用途則要收費):

  3.2 Java規則引擎開源項目

  開源項目的實現主要包括:

  Drools - Drools規則引擎應用Rete演算法的改進形式Rete-II演算法。從內部機制上講,它使用了和Forgy的演算法相同的概念和方法,但是增加了可與物件導向語言無縫串連的節點類型。

  Mandarax 基於反向推理(歸納法)。能夠較容易地實現多個資料來源的整合。例如,資料庫記錄能方便地整合為事實集(facts sets),reflection用來整合物件模型中的功能。目前不支援JSR 94

  OFBiz Rule Engine - 支援歸納法(Backward chaining).最初代碼基於Steven John Metsker的"Building Parsers in Java",不支援JSR 94

  JLisa - JLisa是用來構建商務規則的強大架構,它有著擴充了LISP優秀特色的優點,比Clips還要強大.這些特色對於多範例軟體的開發是至關重要的.支援JSR 94

  其它的開源項目實現有諸如Algernon, TyRuBa, JTP, JEOPS, InfoSapient, RDFExpert, Jena 2, Euler, JLog, Pellet OWL Reasoner, Prova, OpenRules, SweetRules, JShop2等等。

  4、 Java規則引擎API(JSR-94)

  4.1 簡介

  過去大部分的規則引擎開發並沒有正常化,有其自有的API,這使得其與外部程式互動整合不夠靈活。轉而使用另外一種產品時往往意味需要重寫應用程式邏輯和API調用,代價較大。規則引擎工業中標準的缺乏成為令人關注的重要方面。2003年11月定稿並於2004年8月最終發布的JSR 94(Java規則引擎API)使得Java規則引擎的實現得以標準化。

  Java規則引擎API由javax.rules包定義,是訪問規則引擎的標準企業級API。Java規則引擎API允許客戶程式使用統一的方式和不同廠商的規則引擎產品互動,就像使用JDBC編寫獨立於廠商訪問不同的資料庫產品一樣。Java規則引擎API包括建立和管理規則集合的機制,在Working Memory中添加,刪除和修改對象的機制,以及初始化,重設和執行規則引擎的機制。

  4.2 簡介Java規則引擎API體繫結構

  Java規則引擎API分為兩個主要部分:運行時客戶API(the Runtime client API)和規則管理API(the rules administration API)。

  4.2.1規則管理API

  規則管理API在javax.rules.admin中定義,包括裝載規則以及與規則對應的動作(執行集 execution sets)以及執行個體化規則引擎。規則可以從外部資源中裝載,比如說URI,Input streams, XML streams和readers等等.同時管理API提供了註冊和取消註冊執行集以及對執行集進行維護的機制。使用admin包定義規則有助於對客戶訪問運行規則進行控制管理,它通過在執行集上定義許可權使得未經授權的使用者無法訪問受控規則。

  管理API使用類RuleServiceProvider來獲得規則管理(RuleAdministrator)介面的執行個體.規則管理介面提供方法註冊和取消註冊執行集.規則管理員(RuleAdministrator)提供了本地和遠端RuleExecutionSetProvider.在前面已提及,RuleExecutionSetProvider負責建立規則執行集.規則執行集可以從如XML streams, input streams等來源中建立.這些資料來源及其內容經彙集和序列化後傳送到遠端運行規則引擎的伺服器上.大多數應用程式中,遠程規則引擎或遠程規則資料來源的情況並不多見.為了避免這些情況中的網路開銷,API規定了可以從運行在同一JVM中規則庫中讀取資料的本地RuleExecutionSetProvider.

  規則執行集介面除了擁有能夠獲得有關規則執行集的方法,還有能夠檢索在規則執行集中定義的所有規則對象.這使得客戶能夠知道規則集中的規則對象並且按照自己需要來使用它們。

  4.2.2 運行時API

  運行時API定義在javax.rules包中,為規則引擎使用者運行規則獲得結果提供了類和方法。運行時客戶只能訪問那些使用規則管理API註冊過的規則,運行時API協助使用者獲得規則對話並且在這個對話中執行規則。

  運行時API提供了對廠商規則引擎API實現的類似於JDBC的存取方法.規則引擎廠商通過類RuleServiceProvider(類RuleServiceProvider提供了對具體規則引擎實現的運行時和管理API的訪問)將其規則引擎實現提供給客戶,並獲得RuleServiceProvider唯一標識規則引擎的URL.

  URL推薦標準用法是使用類似"com.mycompany.myrulesengine.rules.RuleServiceProvider"這樣的Internet網域名稱空間,這將有助於訪問URL的唯一性.類RuleServiceProvider內部實現了規則管理和運行時訪問所需的介面.所有的RuleServiceProvider要想被客戶所訪問都必須用RuleServiceProviderManager進行註冊。註冊方式類似於JDBC API的DriverManager和Driver。

  運行時介面是運行時API的關鍵區段.運行時介面提供了用於建立規則會話(RuleSession)的方法,規則會話如前所述是用來運行規則的.運行時API同時也提供了訪問在service provider註冊過的所有規則執行集(RuleExecutionSets).規則會話介面定義了客戶使用的會話的類型,客戶根據自己運行規則的方式可以選擇使用有狀態會話或者無狀態會話。

  無狀態會話的工作方式就像一個無狀態會話bean.客戶可以發送單個輸入對象或一列對象來獲得輸出對象.當客戶需要一個與規則引擎間的專用會話時,有狀態會話就很有用.輸入的對象通過addObject() 方法可以加入到會話當中.同一個會話當中可以加入多個對象.對話中已有對象可以通過使用updateObject()方法得到更新.只要客戶與規則引擎間的會話依然存在,會話中的對象就不會丟失。

  RuleExecutionSetMetaData介面提供給客戶讓其尋找規則執行集的中繼資料(metadata).中繼資料通過規則會話介面(RuleSession Interface)提供給使用者。

  使用運行時Runtime API的代碼片斷如下所示:

  RuleServiceProvider ruleProvider = RuleServiceProviderManager.getRuleServiceProvider
   ("com.mycompany.myrulesengine.rules. RuleServiceProvider");
RuleRuntime ruleRuntime = ruleProvider.getRuleRuntime();
StatelessRuleSession ruleSession = (StatelessRuleSession)ruleRuntime.createRuleSession(ruleURL,
   null, RuleRuntime.STTELESS_SESSION_TYPE);
List inputRules = new ArrayList();
inputRules.add(new String("Rule 1"));
inputRules.add(new Integer(1));
List resultRules = ruleSession.executeRules(inputRules);

  4.3 Java規則引擎API安全問題
  
  規則引擎API將管理API和運行時API加以分開,從而為這些包提供了較好粒度的安全控制.規則引擎API並沒有提供明顯的安全機制,它可以和J2EE規範中定義的標準安全API聯合使用.安全可以由以下機制提供,如Java authentication and authorization service (JAAS),the Java cryptography extension (JCE),Java secure Socket Extension (JSSE),或者其它定製的安全API.JAAS能被用來定義規則執行集的許可許可權,從而只有授權使用者才能訪問。

  4.4 異常與日誌

  規則引擎API定義了javax.rules.RuleException作為規則引擎異常層次的根類.所有其它異常都繼承於這個根類.規則引擎中定義的異常都是受控制的異常(checked exceptions),所以捕獲異常的任務就交給了規則引擎。規則引擎API沒有提供明確的日誌機制,但是它建議將Java Logging API用於規則引擎API。

  4.5 JSR 94 小結

  JSR 94 為規則引擎提供了公用標準API,僅僅為實現規則管理API和運行時API提供了指導規範,並沒有提供規則和動作該如何定義以及該用什麼語言定義規則,也沒有為規則引擎如何讀和評價規則提供技術性指導.JSR 94規範將上述問題留給了規則引擎的廠商.在下一節我將簡要介紹一下規則語言。

  5、 規則語言

  JSR 94中沒有涉及用來建立規則和動作的語言.規則語言是規則引擎應用程式的重要組成部分,所有的商務規則都必須用某種語言定義並且儲存於規則執行集中,從而規則引擎可以裝載和處理他們。

  由於沒有關於規則如何定義的公用規範,市場上大多數流行的規則引擎都有其自己的規則語言,目前便有許多種規則語言正在應用,因此,當需要將應用移植到其他的Java規則引擎實現時,可能需要變換規則定義,如將Drools私人的DRL規則語言轉換成標準的ruleML,Jess規則語言轉換成ruleML等。這個工作一般由XSLT轉換器來完成。

  規則語言的詳情這裡不作詳細介紹,名稱及其網址列出如下:

  Rule Markup language (RuleML)
  http://www.ruleml.org/ Simple Rule Markup Language (SRML)
  http://xml.coverpages.org/srml.html Business Rules Markup Language (BRML)
  http://xml.coverpages.org/brml.html SWRL: A Semantic Web Rule Language Combining OWL and RuleML
  http://www.daml.org/2003/11/swrl/

  多種規則語言的使用使得不同規則引擎實現之間的相容性成為問題.通用的規則引擎API或許可以減輕不同廠家API之間的問題,但公用規則語言的缺乏將仍然阻礙不同規則引擎實現之間的互通性.儘管業界在提出公用規則語言上做出了一些努力, 比如說RuleML,SRML的出現,但距離獲得絕大部分規則引擎廠商同意的公用標準還有很長的路要走。

  6、 Java規則引擎API使用樣本

  6.1 設定規則引擎

  Java規則引擎的管理活動階段開始於尋找一個合適的javax.rules.RuleServiceProvider對象,這個對象是應用程式訪問規則引擎的入口。在J2EE環境中,你可能可以通過JNDI獲得RuleServiceProvider。否則,你可以使用javax.rules.RuleServiceProviderManager類:

javax.rules.RuleServiceProviderManager class:
String implName = "org.jcp.jsr94.ri.RuleServiceProvider";
Class.forName(implName);
RuleServiceProvider serviceProvider = RuleServiceProviderManager.getRuleServiceProvider(implName);

  擁有了RuleServiceProvider對象,你就可以獲得一個javax.rules.admin.RuleAdministrator類。從RuleAdministrator類中,你可以得到一個RuleExecutionSetProvider,從類名可以知道,它用於建立javax.rules.RuleExecutionSets對象。RuleExecutionSet基本上是一個裝入記憶體的,準備好執行的規則集合。

  包javax.rules.admin包括兩個不同的RuleExecutionSetProvider類。RuleExecutionSetProvider類本身包括了從Serializable對象建立RuleExecutionSets的方法,因此在規則引擎位於遠程伺服器的情況下,仍然可以使用RuleExecutionSetProvider類,構造器的參數可以通過RMI來傳遞。另一個類是LocalRuleExecutionSetProvider,包含了其他方法,用於從非Serializable資源(如java.io.Reader-本地檔案)建立RuleExectionSets。假設擁有了一個RuleServiceProvider對象,你可以從本地檔案rules.xml檔案建立一個RuleExectionSet對象。如以下的代碼所示:

  RuleAdministrator admin = serviceProvider.getRuleAdministrator();
HashMap properties = new HashMap();
properties.put("name", "My Rules");
properties.put("description", "A trivial rulebase");
FileReader reader = new FileReader("rules.xml");
RuleExecutionSet ruleSet = null;
try {
LocalRuleExecutionSetProvider lresp =admin.getLocalRuleExecutionSetProvider(properties);
ruleSet = lresp.createRuleExecutionSet(reader, properties);
} finally {
reader.close();
}

  接下來,你可以使用RuleAdministrator註冊獲得的RuleExecutionSet,並給它分配一個名稱。在運行時,你可以用同一個名稱建立一個RuleSession;該RuleSession使用了這個命名的RuleExecutionSet。參見下面的用法:admin.registerRuleExecutionSet("rules", ruleSet, properties);

  6.2 執行規則引擎

  在運行時階段,你可以參見一個RuleSession對象。RuleSession對象基本上是一個裝載了特定規則集合的規則引擎執行個體。你從RuleServiceProvider得到一個RuleRuntime對象,接下來,從javax.rules.RuleRuntime得到RuleSession對象。

  RuleSession分為兩類:stateful和stateless。它們具有不同的功能。StatefulRuleSession的Working Memory能夠在多個方法調用期間儲存狀態。你可以在多個方法調用期間在Working Memory中加入多個對象,然後執行引擎,接下來還可以加入更多的對象並再次執行引擎。相反,StatelessRuleSession類是不儲存狀態的,為了執行它的executeRules方法,你必須為Working Memory提供所有的初始資料,執行規則引擎,得到一個內容列表作為傳回值。

  下面的例子中,我們建立一個StatefulRuleSession執行個體,添加兩個對象(一個Integer和一個String)到Working Memory,執行規則,然後得到Working Memory中所有的內容,作為java.util.List對象返回。最後,我們調用release方法清理RuleSession:

  RuleRuntime runtime = rsp.getRuleRuntime(); 
 StatefulRuleSession session = (StatefulRuleSession)runtime.createRuleSession("rules",
properties,RuleRuntime.STATEFUL_SESSION_TYPE);
 session.addObject(new Integer(1));
session.addObject("A string");
session.executeRules();
List results = session.getObjects();
session.release();

   7、 結束語

  Java規則引擎API(JSR-94)允許客戶程式使用統一的方式和不同廠商的規則引擎產品互動,一定程度上給規則引擎廠商提供了標準化規範。但其幾乎沒有定義什麼是規則引擎,當然也沒有深入到規則是如何構建和操縱的,規則調用的效用,規則與Java語言的綁定等方面。並且JSR-94在對J2EE的支援上也不足。規則語言的標準化,JSR-94的進一步的充實深化都有待研究。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.