posts - 15,  comments - 34,  trackbacks - 27

          內(nèi)容提要
          在本文的第一部分,我將討論規(guī)則引擎如何幫助你從軟件的應(yīng)用邏輯中分離出商業(yè)規(guī)則邏輯,以實(shí)現(xiàn)商業(yè)應(yīng)用的靈活性。在第二部分,我還將介紹 JSR 94 規(guī)則引擎 API ,及其實(shí)現(xiàn)原理。在第三部分 , 介紹其開(kāi)源實(shí)現(xiàn) Drools 項(xiàng)目,它是這一新技術(shù)的先驅(qū),并詳解一個(gè)規(guī)則引擎例子。

          ?

          一、規(guī)則引擎如何幫助你從軟件的應(yīng)用邏輯中分離出商業(yè)規(guī)則邏輯,以實(shí)現(xiàn)商業(yè)應(yīng)用的靈活性。

          定義 :

          規(guī)則引擎:由基于規(guī)則的專家系統(tǒng)中的推理引擎發(fā)展而來(lái) , 是一種嵌入在應(yīng)用程序中的組件,實(shí)現(xiàn)了將業(yè)務(wù)決策從應(yīng)用程序代碼中分離出來(lái),并使用預(yù)定義的語(yǔ)義模塊編寫(xiě)業(yè)務(wù)決策。接受數(shù)據(jù)輸入,解釋業(yè)務(wù)規(guī)則,并根據(jù)規(guī)則做出業(yè)務(wù)決策。

          為什么使用規(guī)則引擎
          “任何事物都會(huì)改變,唯一不變的是變化”…,這些陳詞濫調(diào)已經(jīng)在我們耳邊磨出糨子來(lái)了. 無(wú)論是快速軟件開(kāi)發(fā),極限編程,還是敏捷軟件開(kāi)發(fā)等,它們 無(wú)一例外地強(qiáng)調(diào)靈活和變化的重要性。

          雖然IT團(tuán)隊(duì)反應(yīng)迅速,但他們通常帶來(lái)"電話效應(yīng)"――IT給商業(yè)計(jì)劃的執(zhí)行帶來(lái)的阻力和它帶來(lái)的利益一樣多。不幸的是,在開(kāi)發(fā)團(tuán)隊(duì)完全理解商業(yè)決策規(guī)則并實(shí)現(xiàn)之前,規(guī)則已經(jīng)改變了。在軟件進(jìn)入市場(chǎng)前,它已經(jīng)過(guò)時(shí)了,需要進(jìn)行重構(gòu)以滿足新的業(yè)務(wù)需求。如果你是一個(gè)開(kāi)發(fā)人員,你會(huì)知道我在說(shuō)什么。再也沒(méi)有比 在需求變動(dòng)的情況下構(gòu)造軟件讓開(kāi)發(fā)人員更沮喪的事情了。作為軟件開(kāi)發(fā)人員,你必須比業(yè)務(wù)人員更了解業(yè)務(wù),有時(shí)還要了解更多。
          ???
          試想一下在完成產(chǎn)品開(kāi)發(fā)時(shí),需求(市場(chǎng)環(huán)境或人為因素,有些需求無(wú)法在項(xiàng)目初始就能預(yù)見(jiàn)的)和規(guī)劃產(chǎn)品開(kāi)發(fā)時(shí)相比,已經(jīng)發(fā)生了根本變化。現(xiàn)在你必須要遵守新的規(guī)則,你已經(jīng)喪失了你的邊際優(yōu)勢(shì),而且設(shè) 計(jì)軟件的五人中的三人已經(jīng)離開(kāi)了公司。你必須給接手的新人重新講解復(fù)雜的業(yè)務(wù)。如果事情不順利,你可能發(fā)現(xiàn)自己要對(duì)付一個(gè)缺少文檔,并且你完全不了解的遺留應(yīng)用。
          你的戰(zhàn)略在哪出現(xiàn)了問(wèn)題?你在哪里應(yīng)該可以做到更好?當(dāng)前在Java社區(qū),一個(gè)引人注目的新技術(shù)是,分離商業(yè)決策者的商業(yè)決策邏輯和應(yīng)用開(kāi)發(fā)者的技術(shù)決策,并把這些商業(yè)決策放在中心數(shù)據(jù)庫(kù),讓它們能在運(yùn)行時(shí)(即商務(wù)時(shí)間)可以動(dòng)態(tài)地管理和修改。這是一個(gè)你值得考慮的策略。
          為什么你的開(kāi)發(fā)團(tuán)隊(duì)不得在代碼中包含復(fù)雜微妙的商業(yè)決策邏輯呢?你怎樣才能向他們解釋決策推理的微妙之處呢?你這樣做是否謹(jǐn)慎呢?可能不是。你一方面要應(yīng)付市場(chǎng),一方面要應(yīng)付軟件代碼,這實(shí)在太困難了。如果能將這些商業(yè)決策規(guī)則集中地放在一個(gè)地方,以一種你可以理解的格式定義,讓你可以直接管理,而不是散落在代碼的各個(gè)角落,那該有多好。如果你能把商業(yè)決策規(guī)則獨(dú)立于你的軟件代碼,讓開(kāi)發(fā)團(tuán)隊(duì)作出技術(shù)決策,你將會(huì)獲得更多好處。你的項(xiàng)目開(kāi)發(fā)周期會(huì)更短,軟件對(duì)于變動(dòng)的需求更靈活。

          ?

          分離業(yè)務(wù)和技術(shù)的關(guān)注點(diǎn)

          這是一個(gè)非常簡(jiǎn)單的例子,從業(yè)務(wù)人員的角度,說(shuō)明如何分離商務(wù)和技術(shù)的關(guān)注點(diǎn)。 CRM 系統(tǒng)新裝 ADSL 。系統(tǒng)的一部分用于分析并受理可供客戶購(gòu)買(mǎi)的銷售品 , 并在需要時(shí)向你提出相應(yīng)的提示。這個(gè)系統(tǒng)的工作是,識(shí)別出產(chǎn)品,并標(biāo)記出來(lái)以便進(jìn)一步的檢查。
          前置條件 :

          CRM 開(kāi)發(fā)團(tuán)隊(duì)擁有一大堆數(shù)據(jù),并開(kāi)發(fā)了一系列你可以在規(guī)則中引用的簡(jiǎn)單數(shù)據(jù)對(duì)象。現(xiàn)在,為簡(jiǎn)單起見(jiàn),假設(shè)你是一名受過(guò)良好教育的,了解技術(shù)的管理人,你了解 XML 的基本知識(shí),可以讓你編寫(xiě)和修改簡(jiǎn)單的 XML 規(guī)則文件。
          你的第一個(gè)規(guī)則是,給在眾多受理的產(chǎn)品 ( 有上百個(gè)產(chǎn)品 , 且只有一個(gè)入口和一個(gè)出品 ) 中剔除非 ADSL 的產(chǎn)品(這有點(diǎn)過(guò)分簡(jiǎn)化,但這里只作為一個(gè)例子) , 并給 ADSL 承載電話進(jìn)行合法性校驗(yàn)。該電話先前不能有承載的 ADSL. 。對(duì)于這個(gè)簡(jiǎn)單的例子,你的規(guī)則文件看起來(lái)如下(我們將會(huì)過(guò)頭來(lái)討論這個(gè)文件的結(jié)構(gòu)):

          < rule? name ="Prd_1-0-A1-1307?-01?" > ?
          < java:condition > map.get(?“?prdId?”?).equals("1307") </ java:condition > ?
          < java:condition > map.get(?“?count?”?) < 1 </java:condition > ?
          < java:consequence > bean.setPass(true); </ java:consequence > ?
          </ rule > ?



          半個(gè)月后,你接到電信公司的電話,對(duì)于 ADSL 選擇寬帶上網(wǎng)卡的用戶承電話承載的 ADSL 可不受限制。除此之外,你的客戶還要求 XXX 本地網(wǎng)內(nèi)的某類客戶承載電話承載的 ADSL 不能超過(guò) 5 個(gè)。
          你啟動(dòng)規(guī)則編輯器,并修改規(guī)則以匹配新的評(píng)估條件。完成規(guī)則文件修改后,看起來(lái)如下:

          < rule? name ="Prd_1-0-A1-1307-01" > ?

          < java:condition > map.get(?“?prdId?”?).equals("1307") </ java:condition > ?
          < java:condition > !map.get(?“?計(jì)費(fèi)方式?”?).equals(?“?寬帶上網(wǎng)卡?”?) </ java:condition > ?
          < java:condition > map.get(?“?count?”?) < 1 </java:condition > ?
          < java:consequence > bean.setPass(true); </ java:consequence > ?
          </ rule > ???

          < rule? name ="Prd_1-0-A1-1307-02" > ?
          < java:condition > map.get(?“?prdId?”?).equals("1307") </ java:condition > ?
          < java:condition > map.get(?“?計(jì)費(fèi)方式?”?).equals(?“?寬帶上網(wǎng)卡?”?) </ java:condition > ?
          < java:condition > (map.get(?“?latnId?”?).equals(?“?552?”?)& &map .get(?“?count?”?)<5)?||?!map.get(?“?latnId?”?).equals(?“?552?”?) </ java:condition > ?
          < java:consequence > bean.setPass(true); </ java:consequence > ?
          </ rule > ?


          你無(wú)需為此向開(kāi)發(fā)團(tuán)隊(duì)作任何解釋。你無(wú)需等待他們開(kāi)發(fā)或測(cè)試程序。如果你的規(guī)則引擎的語(yǔ)義足夠強(qiáng)大,讓你描述工作數(shù)據(jù),你可以隨時(shí)按需修改商業(yè)規(guī)則。
          現(xiàn)在,我希望你已經(jīng)清楚以下的原則:在這個(gè)例子中, ADSL 承載電話是否合法是一個(gè)業(yè)務(wù)決策,而不是技術(shù)決策。決定將哪個(gè)承載電話是否通過(guò)是業(yè)務(wù)人員的邏輯 。業(yè)務(wù)人員作出這些決策,并可以按需定制應(yīng)用。這些規(guī)則因此變成了一種控制界面,一種新的商業(yè)系統(tǒng)用戶界面。

          ?

          二、 Java 規(guī)則引擎 API JSR-94, 及其實(shí)現(xiàn)原理。
          2003 11 月, 為了使規(guī)則引擎技術(shù)標(biāo)準(zhǔn)化, Java 社區(qū)制定了 Java 規(guī)則引擎 API JSR94 )規(guī)范。它為 Java 平臺(tái)訪問(wèn)規(guī)則引擎定義了一些簡(jiǎn)單的 API 這個(gè)新的 API 讓開(kāi)發(fā)人員在運(yùn)行時(shí)訪問(wèn)和執(zhí)行規(guī)則有了統(tǒng)一的標(biāo)準(zhǔn)方式。隨著新規(guī)范產(chǎn)品實(shí)現(xiàn)的成熟和推向市場(chǎng),開(kāi)發(fā) 團(tuán)隊(duì)將可以從應(yīng)用代碼中抽取出商業(yè)決策邏輯。

              Java 規(guī)則引擎 API javax.rules 包中定義,是訪問(wèn)規(guī)則引擎的標(biāo)準(zhǔn)企業(yè)級(jí) API Java 規(guī)則引擎 API 允許客戶程序使用統(tǒng)一的方式和不 同廠商的規(guī)則引擎產(chǎn)品交互,就如同使用 JDBC 編寫(xiě)?yīng)毩⒂趶S商訪問(wèn)不同的數(shù)據(jù)庫(kù)產(chǎn)品一樣。 Java 規(guī)則引擎 API 包括創(chuàng)建和管理規(guī)則集合的機(jī)制,在工作區(qū) 中添加,刪除和修改對(duì)象的機(jī)制,以及初始化,重置和執(zhí)行規(guī)則引擎的機(jī)制。 Java 規(guī)則引擎 API 主要由兩大類 API 組成 : 規(guī)則管理 API(The Rules Administrator API) 和運(yùn)行時(shí)客戶 API(The Runtime Client API)

          ?

          Java 規(guī)則引擎是一種嵌入在 Java 程序中的組件,它的任務(wù)是把當(dāng)前提交給引擎的 Java 數(shù)據(jù)對(duì)象與加載在引擎中的業(yè)務(wù)規(guī)則進(jìn)行測(cè)試和比對(duì),激活那些符合當(dāng)前數(shù)據(jù)狀態(tài)下的業(yè)務(wù)規(guī)則,根據(jù)業(yè)務(wù)規(guī)則中聲明的執(zhí)行邏輯,觸發(fā)應(yīng)用程序中對(duì)應(yīng)的操作。

          ?

          Java 規(guī)則引擎的工作機(jī)制與上述規(guī)則引擎機(jī)制十分類似,只不過(guò)對(duì)上述概念進(jìn)行了重新包裝組合。Java規(guī)則引擎對(duì)提交給引擎的Java數(shù)據(jù)對(duì)象進(jìn)行檢 索,根據(jù)這些對(duì)象的當(dāng)前屬性值和它們之間的關(guān)系,從加載到引擎的規(guī)則集中發(fā)現(xiàn)符合條件的規(guī)則,創(chuàng)建這些規(guī)則的執(zhí)行實(shí)例。這些實(shí)例將在引擎接到執(zhí)行指令時(shí)、依照某種優(yōu)先序依次執(zhí)行。一般來(lái)講,Java規(guī)則引擎內(nèi)部由下面幾個(gè)部分構(gòu)成:工作內(nèi)存(Working Memory)即工作區(qū),用于存放被引擎引用的數(shù)據(jù)對(duì)象集合;規(guī)則執(zhí)行隊(duì)列,用于存放被激活的規(guī)則執(zhí)行實(shí)例;靜態(tài)規(guī)則區(qū),用于存放所有被加載的業(yè)務(wù)規(guī)則, 這些規(guī)則將按照某種數(shù)據(jù)結(jié)構(gòu)組織,當(dāng)工作區(qū)中的數(shù)據(jù)發(fā)生改變后,引擎需要迅速根據(jù)工作區(qū)中的對(duì)象現(xiàn)狀,調(diào)整規(guī)則執(zhí)行隊(duì)列中的規(guī)則執(zhí)行實(shí)例。Java規(guī)則引 擎的結(jié)構(gòu)示意圖如下圖所示。


          {8B1EC1F7-E158-440C-8ECE-6CB439EC382D}0.jpg?

          ?
          Java規(guī)則引擎工作機(jī)制


             當(dāng)引擎執(zhí)行時(shí),會(huì)根據(jù)規(guī)則執(zhí)行隊(duì)列中的優(yōu)先順序逐條執(zhí)行規(guī)則執(zhí)行實(shí)例,由于規(guī)則的執(zhí)行部分可能會(huì)改變工作區(qū)的數(shù)據(jù)對(duì)象,從而會(huì)使隊(duì)列中的某些規(guī)則執(zhí)行實(shí)例因?yàn)闂l件改變而失效,必須從隊(duì)列中撤銷,也可能會(huì)激活原來(lái)不滿足條件的規(guī)則,生成新的規(guī)則執(zhí)行實(shí)例進(jìn)入隊(duì)列。于是就產(chǎn)生了一種動(dòng)態(tài)的規(guī)則執(zhí)行鏈,形 成規(guī)則的推理機(jī)制。這種規(guī)則的鏈?zhǔn)?span lang="EN-US">”反應(yīng)完全是由工作區(qū)中的數(shù)據(jù)驅(qū)動(dòng)的。

            任何一個(gè)規(guī)則引擎都需要很好地解決規(guī)則的推理機(jī)制和規(guī) 則條件匹配的效率問(wèn)題。規(guī)則條件匹配的效率決定了引擎的性能,引擎需要迅速測(cè)試工作區(qū)中的數(shù)據(jù)對(duì)象,從加載的規(guī)則集中發(fā)現(xiàn)符合條件的規(guī)則,生成規(guī)則執(zhí)行實(shí)例。1982年美國(guó)卡耐基?梅隆大學(xué)的Charles L. Forgy發(fā)明了一種叫Rete算法,很好地解決了這方面的問(wèn)題。目前世界頂尖的商用業(yè)務(wù)規(guī)則引擎產(chǎn)品基本上都使用Rete算法。

          ?

          三、開(kāi)源實(shí)現(xiàn) Drools 項(xiàng)目

          現(xiàn)在,我要介紹 Drools 項(xiàng)目, Charles Forgy Rete 算法的一個(gè)增強(qiáng)的 Java 語(yǔ)言實(shí)現(xiàn)。 Drools 是一個(gè) Bob McWhirter 開(kāi)發(fā)的開(kāi)源項(xiàng)目,放在 The Codehaus 上。在我寫(xiě)這篇文章時(shí), Drools 發(fā)表了 2.0-beata-14 版。在 CVS 中,已完整地實(shí)現(xiàn)了 JSR94 Rule Engine API 并提供了單元測(cè)試代碼。
          Rete
          算法是 Charles Forgy 1979 年發(fā)明的,是目前用于生產(chǎn)系統(tǒng)的效率最高的算法(除了私有的 Rete II )。 Rete 是唯一的,效率與執(zhí)行規(guī)則數(shù)目無(wú)關(guān)的決策支持算法。 For the uninitiated, that means it can scale to incorporate and execute hundreds of thousands of rules in a manner which is an order of magnitude more efficient then the next best algorithm Rete 應(yīng)用于生產(chǎn)系統(tǒng)已經(jīng)有很多年了,但在 Java 開(kāi)源軟件中并沒(méi)有得到廣泛應(yīng)用(討論 Rete 算法的文檔參見(jiàn) http: //herzberg.ca.sandia.gov/jess/docs/61/rete.html 。)。
          除了應(yīng)用了 Rete 核心算法,開(kāi)源軟件 License 100 %的 Java 實(shí)現(xiàn)之外, Drools 還提供了很多有用的特性。其中包括實(shí)現(xiàn)了 JSR94 API 和創(chuàng)新的規(guī)則語(yǔ)義系統(tǒng),這個(gè)語(yǔ)義系統(tǒng)可用來(lái)編寫(xiě)描述規(guī)則的語(yǔ)言。目前, Drools 提供了三種語(yǔ)義模塊 ――Python 模塊, Java 模塊和 Groovy 模塊。本文余下部分集中討論 JSR94 API ,我將在第二篇文章中討論語(yǔ)義系統(tǒng)。
          作為使用 javax.rules API 的開(kāi)發(fā)人員,你的目標(biāo)是構(gòu)造一個(gè) RuleExecutionSet 對(duì)象,并在運(yùn)行時(shí)通過(guò)它獲得一個(gè) RuleSession 對(duì)象。為了簡(jiǎn)化這個(gè)過(guò)程, 我編寫(xiě)了一個(gè)規(guī)則引擎 API fa?ade ,可以用來(lái)解釋代表 Drools DRL 文件的 InputStream ,并構(gòu)造一個(gè) RuleExecutionSet 對(duì)象。
          在上面提到了 Drools 的三種語(yǔ)義模塊,我接下來(lái)使用它們重新編寫(xiě)上面的例子 XML 規(guī)則文件。這個(gè)例子中我選擇 Java 模塊。使用 Java 模塊重新編寫(xiě)的規(guī)則文件如下:

          < rule-set? name ="fibonacci" ?xmlns =http://drools.org/rules
          ???????xmlns:java
          ="http://drools.org/semantics/java" ?xmlns:xs =http://www.w3.org/2001/XMLSchema-instance ???xs:schemaLocation ="http://drools.org/rules?rules.xsd?http://drools.org/semantics/java?java.xsd" >

          < import > java.util.* </ import >
          < application-data? identifier ="request" > javax.servlet.http.HttpServletRequest </ application-data >
          < java:functions >
          public?static?int?countAdslByTel(HttpServletRequest?request)throws?Exception{
          ???????PrdInstDAO?prdInstDAO=new?PrdInstDAO?(request.getParameter(“l(fā)atnId”));
          ???????Return?prdInstDAO.countAdslByTel(request.getParameter(“service_nbr”))?;
          }

          </ java:functions >
          < rule? name ="Prd_1-0-A1-1307" ?salience ="1" ?no-loop ="true" >
          < parameter? identifier ="map" >< class > Map </ class ></ parameter >
          < parameter? identifier ="bean" > < class > AcceptReqBean </ class ></ parameter >
          < java:condition > map.get(“prdId”).equals("1307") </ java:condition >
          < java:consequence >
          Int?count=??????countAdslByTel(request);
          If(map.get(“計(jì)費(fèi)方式”).equals(“寬帶上網(wǎng)卡”)){
          ???????If(map.get(“l(fā)atnId”).equals(“552”)&
          &count >=5){
          ???????bean.setPass(false);
          }else
          ???bean.setPass(true);
          }else{
          ???????If(count
          < 1 ){
          bean.setPass(true);
          }else{
          ???????bean.setPass(false);
          ???????}
          }
          </java:consequence
          >
          </ rule >
          </ rule-set >

          現(xiàn)在的規(guī)則文件并沒(méi)有上面的簡(jiǎn)潔明了。別擔(dān)心,我們將在下一篇文章討論語(yǔ)義模塊。現(xiàn)在,請(qǐng)注意觀察XML文件的結(jié)構(gòu)。其中一個(gè)rule-set元素包含了一個(gè)或多個(gè)rule元素,rule元素又包含了parameterconditionconsequence元素。Condition consequence元素包含的內(nèi)容和Java很象。注意,在這些元素中,有些事你可以做,有些事你不能做。目前,Drools使用 BeanShell2.0b1作為它的Java解釋器。我在這里并不想詳細(xì)的討論DRL文件和Java語(yǔ)義模塊的語(yǔ)法。我們的目標(biāo)是解釋如何使用 DroolsJSR94 API
          Drools項(xiàng)目CVSdrools-jsr94模塊中,單元測(cè)試代碼包含了一個(gè)ExampleRuleEngineFacade對(duì)象,它基于 Brian ToppingDentaku項(xiàng)目。這個(gè)facade對(duì)象通過(guò)javax.rules API,創(chuàng)建了供RuleExecutionSetRuleSession使用的一系列對(duì)象。它并沒(méi)有完全包括了Drools引擎API的所有特性和細(xì)微差別,但可以作為新手使用API的一個(gè)簡(jiǎn)單例子。
          下面的代碼片斷顯示如何在程序中調(diào)用drools規(guī)則引擎并執(zhí)行

          ?

          // ?執(zhí)行規(guī)則引擎
          ????????RulesEngine?rulesEngine = new ?RulesEngine(url);
          ????????List?rulesResult
          = rulesEngine.executeRules( new ?WorkingEnvironmentCallback() {
          ????????????
          public ? void ?initEnvironment(WorkingMemory?workingMemory)? throws ?FactException {
          ??????????????????????workingMemory.assertObject(..);
          ??????????????????????workingMemory.setApplicationData(
          " map " ,map);..
          ????????????}

          ????????}
          );

          ?public interface WorkingEnvironmentCallback{

          ?void initEnvironment(WorkingMemory workingMemory) throws FactException;
          }?

          public?class?RulesEngine{
          ????
          private?static?Logger????logger????=Logger.getLogger(RulesEngine.class);
          ????
          private?RuleBase????????rules;
          ????
          private?String????????????rulesFile;
          ????
          private?boolean????????????debug????=false;

          ????
          /**
          ?????*?構(gòu)造方法,裝載規(guī)則文件
          ?????*?
          ?????*?
          @param?rulesFile
          ?????*????????????絕對(duì)規(guī)則文件路徑
          ?????*?
          @throws?RulesEngineException
          ?????
          */

          ????
          public?RulesEngine(final?String?rulesFile)?throws?RulesEngineException{
          ????????
          super();
          ????????
          this.rulesFile=rulesFile;
          ????????
          try{
          ????????????
          ????rules=RuleBaseLoader.loadFromInputStream(new?BufferedInputStream(new?FileInputStream(
          ????????????????????????
          new?File(rulesFile))));????????????}

          ????????}
          catch(Exception?e){
          ????????????e.printStackTrace();
          ????????????
          throw?new?RulesEngineException("Could?not?load?rules?file:?"?+?rulesFile,e);
          ????????}

          ????}


          ????
          public?RulesEngine(final?URL?rulesFile)?throws?RulesEngineException{
          ????????
          super();
          ????????
          this.rulesFile=rulesFile.getPath();
          ????????
          try{????????????????rules=RuleBaseLoader.loadFromUrl(rulesFile);
          ????????????????
          ????????????}

          ????????}
          catch(Exception?e){
          ????????????e.printStackTrace();
          ????????????
          throw?new?RulesEngineException("Could?not?load?rules?file:?"?+?rulesFile,e);
          ????????}

          ????}


          ????
          /**
          ?????*?構(gòu)造方法,裝載規(guī)則文件/debug模式
          ?????*?
          ?????*?
          @param?rulesFile
          ?????*?
          @param?debug
          ?????*?
          @throws?RulesEngineException
          ?????
          */

          ????
          public?RulesEngine(URL?rulesFile,boolean?debug)?throws?RulesEngineException{
          ????????
          this(rulesFile);
          ????????
          this.debug=debug;
          ????}


          ????
          /**
          ?????*?構(gòu)造方法,裝載規(guī)則文件/debug模式
          ?????*?
          ?????*?
          @param?rulesFile
          ?????*?
          @param?debug
          ?????*?
          @throws?RulesEngineException
          ?????
          */

          ????
          public?RulesEngine(String?rulesFile,boolean?debug)?throws?RulesEngineException{
          ????????
          this(rulesFile);
          ????????
          this.debug=debug;
          ????}


          ????
          /**
          ?????*?執(zhí)行規(guī)則
          ?????*?
          ?????*?
          @param?callback
          ?????*?
          @return
          ?????*?
          @throws?RulesEngineException
          ?????
          */

          ????
          public?List?executeRules(WorkingEnvironmentCallback?callback)?throws?RulesEngineException{
          ????????
          try{
          ????????????WorkingMemory?workingMemory
          =rules.newWorkingMemory();
          ????????????
          if(debug){
          ????????????????workingMemory.addEventListener(
          new?DebugWorkingMemoryEventListener());

          ????????????}

          ????????????callback.initEnvironment(workingMemory);
          ????????????workingMemory.fireAllRules();
          ????????????
          return?workingMemory.getObjects();
          ????????}
          catch(FactException?fe){
          ????????????logFactException(fe);
          ????????????
          throw?new?RulesEngineException("Exception?occurred?while?attempting?to?execute?"?+?"rules?file:?"
          ????????????????????
          +?rulesFile,fe);
          ????????}

          ????}


          ????
          private?void?logFactException(FactException?fe){
          ????????
          if(fe?instanceof?ConditionException){
          ????????????ConditionException?ce
          =(ConditionException)fe;
          ????????????logger.error(
          "Rule?where?condition?exception?occurred:?"?+?ce.getRule().getName());
          ????????}
          else?if(fe?instanceof?ConsequenceException){
          ????????????ConsequenceException?ce
          =(ConsequenceException)fe;
          ????????????logger.error(
          "Information?about?the?consequence?failure:?"?+?ce.getInfo());
          ????????????logger.error(
          "Rule?where?consequence?exception?occurred:?"?+?ce.getRule().getName());
          ????????}

          ????}


          }

          結(jié)束語(yǔ)



            規(guī)則引擎技術(shù)為管理多變的業(yè)務(wù)邏輯提供了一種解決方案。規(guī)則引擎既可以管理應(yīng)用層的業(yè)務(wù)邏輯又可以使表示層的頁(yè)面流程可訂制。這就給軟件架構(gòu)師設(shè)計(jì)大型信息系統(tǒng)提供了一項(xiàng)新的選擇。而 Java 規(guī)則引擎在 Java 社區(qū)制定標(biāo)準(zhǔn)規(guī)范以后必將獲得更大發(fā)展。
          posted on 2006-11-27 22:15 jacky 閱讀(2999) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(10)

          隨筆檔案

          文章分類

          文章檔案

          相冊(cè)

          收藏夾

          java

          搜索

          •  

          最新評(píng)論


          主站蜘蛛池模板: 江永县| 丹阳市| 林口县| 禹州市| 绍兴县| 株洲县| 达州市| 司法| 游戏| 宜都市| 神农架林区| 集贤县| 满洲里市| 邯郸市| 阜新市| 图木舒克市| 额济纳旗| 若尔盖县| 防城港市| 滕州市| 沈阳市| 镇原县| 上林县| 旌德县| 泗阳县| 潮州市| 包头市| 恩施市| 健康| 宿州市| 昌都县| 灵石县| 莱芜市| 平安县| 阜宁县| 松滋市| 新邵县| 颍上县| 手游| 博湖县| 玛纳斯县|