<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>


    posts - 15,  comments - 34,  trackbacks - 27

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

    ?

    一、規則引擎如何幫助你從軟件的應用邏輯中分離出商業規則邏輯,以實現商業應用的靈活性。

    定義 :

    規則引擎:由基于規則的專家系統中的推理引擎發展而來 , 是一種嵌入在應用程序中的組件,實現了將業務決策從應用程序代碼中分離出來,并使用預定義的語義模塊編寫業務決策。接受數據輸入,解釋業務規則,并根據規則做出業務決策。

    為什么使用規則引擎
    “任何事物都會改變,唯一不變的是變化”…,這些陳詞濫調已經在我們耳邊磨出糨子來了. 無論是快速軟件開發,極限編程,還是敏捷軟件開發等,它們 無一例外地強調靈活和變化的重要性。

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

    ?

    分離業務和技術的關注點

    這是一個非常簡單的例子,從業務人員的角度,說明如何分離商務和技術的關注點。 CRM 系統新裝 ADSL 。系統的一部分用于分析并受理可供客戶購買的銷售品 , 并在需要時向你提出相應的提示。這個系統的工作是,識別出產品,并標記出來以便進一步的檢查。
    前置條件 :

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

    < 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 > ?



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

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

    < java:condition > map.get(?“?prdId?”?).equals("1307") </ java:condition > ?
    < java:condition > !map.get(?“?計費方式?”?).equals(?“?寬帶上網卡?”?) </ 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(?“?計費方式?”?).equals(?“?寬帶上網卡?”?) </ 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 > ?


    你無需為此向開發團隊作任何解釋。你無需等待他們開發或測試程序。如果你的規則引擎的語義足夠強大,讓你描述工作數據,你可以隨時按需修改商業規則。
    現在,我希望你已經清楚以下的原則:在這個例子中, ADSL 承載電話是否合法是一個業務決策,而不是技術決策。決定將哪個承載電話是否通過是業務人員的邏輯 。業務人員作出這些決策,并可以按需定制應用。這些規則因此變成了一種控制界面,一種新的商業系統用戶界面。

    ?

    二、 Java 規則引擎 API JSR-94, 及其實現原理。
    2003 11 月, 為了使規則引擎技術標準化, Java 社區制定了 Java 規則引擎 API JSR94 )規范。它為 Java 平臺訪問規則引擎定義了一些簡單的 API 這個新的 API 讓開發人員在運行時訪問和執行規則有了統一的標準方式。隨著新規范產品實現的成熟和推向市場,開發 團隊將可以從應用代碼中抽取出商業決策邏輯。

        Java 規則引擎 API javax.rules 包中定義,是訪問規則引擎的標準企業級 API Java 規則引擎 API 允許客戶程序使用統一的方式和不 同廠商的規則引擎產品交互,就如同使用 JDBC 編寫獨立于廠商訪問不同的數據庫產品一樣。 Java 規則引擎 API 包括創建和管理規則集合的機制,在工作區 中添加,刪除和修改對象的機制,以及初始化,重置和執行規則引擎的機制。 Java 規則引擎 API 主要由兩大類 API 組成 : 規則管理 API(The Rules Administrator API) 和運行時客戶 API(The Runtime Client API)

    ?

    Java 規則引擎是一種嵌入在 Java 程序中的組件,它的任務是把當前提交給引擎的 Java 數據對象與加載在引擎中的業務規則進行測試和比對,激活那些符合當前數據狀態下的業務規則,根據業務規則中聲明的執行邏輯,觸發應用程序中對應的操作。

    ?

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


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

    ?
    Java規則引擎工作機制


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

      任何一個規則引擎都需要很好地解決規則的推理機制和規 則條件匹配的效率問題。規則條件匹配的效率決定了引擎的性能,引擎需要迅速測試工作區中的數據對象,從加載的規則集中發現符合條件的規則,生成規則執行實例。1982年美國卡耐基?梅隆大學的Charles L. Forgy發明了一種叫Rete算法,很好地解決了這方面的問題。目前世界頂尖的商用業務規則引擎產品基本上都使用Rete算法。

    ?

    三、開源實現 Drools 項目

    現在,我要介紹 Drools 項目, Charles Forgy Rete 算法的一個增強的 Java 語言實現。 Drools 是一個 Bob McWhirter 開發的開源項目,放在 The Codehaus 上。在我寫這篇文章時, Drools 發表了 2.0-beata-14 版。在 CVS 中,已完整地實現了 JSR94 Rule Engine API 并提供了單元測試代碼。
    Rete
    算法是 Charles Forgy 1979 年發明的,是目前用于生產系統的效率最高的算法(除了私有的 Rete II )。 Rete 是唯一的,效率與執行規則數目無關的決策支持算法。 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 應用于生產系統已經有很多年了,但在 Java 開源軟件中并沒有得到廣泛應用(討論 Rete 算法的文檔參見 http: //herzberg.ca.sandia.gov/jess/docs/61/rete.html 。)。
    除了應用了 Rete 核心算法,開源軟件 License 100 %的 Java 實現之外, Drools 還提供了很多有用的特性。其中包括實現了 JSR94 API 和創新的規則語義系統,這個語義系統可用來編寫描述規則的語言。目前, Drools 提供了三種語義模塊 ――Python 模塊, Java 模塊和 Groovy 模塊。本文余下部分集中討論 JSR94 API ,我將在第二篇文章中討論語義系統。
    作為使用 javax.rules API 的開發人員,你的目標是構造一個 RuleExecutionSet 對象,并在運行時通過它獲得一個 RuleSession 對象。為了簡化這個過程, 我編寫了一個規則引擎 API fa?ade ,可以用來解釋代表 Drools DRL 文件的 InputStream ,并構造一個 RuleExecutionSet 對象。
    在上面提到了 Drools 的三種語義模塊,我接下來使用它們重新編寫上面的例子 XML 規則文件。這個例子中我選擇 Java 模塊。使用 Java 模塊重新編寫的規則文件如下:

    < 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(“latnId”));
    ???????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(“計費方式”).equals(“寬帶上網卡”)){
    ???????If(map.get(“latnId”).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 >

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

    ?

    // ?執行規則引擎
    ????????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;

    ????
    /**
    ?????*?構造方法,裝載規則文件
    ?????*?
    ?????*?
    @param?rulesFile
    ?????*????????????絕對規則文件路徑
    ?????*?
    @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);
    ????????}

    ????}


    ????
    /**
    ?????*?構造方法,裝載規則文件/debug模式
    ?????*?
    ?????*?
    @param?rulesFile
    ?????*?
    @param?debug
    ?????*?
    @throws?RulesEngineException
    ?????
    */

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


    ????
    /**
    ?????*?構造方法,裝載規則文件/debug模式
    ?????*?
    ?????*?
    @param?rulesFile
    ?????*?
    @param?debug
    ?????*?
    @throws?RulesEngineException
    ?????
    */

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


    ????
    /**
    ?????*?執行規則
    ?????*?
    ?????*?
    @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());
    ????????}

    ????}


    }

    結束語



      規則引擎技術為管理多變的業務邏輯提供了一種解決方案。規則引擎既可以管理應用層的業務邏輯又可以使表示層的頁面流程可訂制。這就給軟件架構師設計大型信息系統提供了一項新的選擇。而 Java 規則引擎在 Java 社區制定標準規范以后必將獲得更大發展。
    posted on 2006-11-27 22:15 jacky 閱讀(2996) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    <2006年11月>
    2930311234
    567891011
    12131415161718
    19202122232425
    262728293012
    3456789

    常用鏈接

    留言簿(10)

    隨筆檔案

    文章分類

    文章檔案

    相冊

    收藏夾

    java

    搜索

    •  

    最新評論


    主站蜘蛛池模板: 2019亚洲午夜无码天堂| 在线观看成人免费| 免费人成网站永久| 亚洲一区二区三区91| 亚洲成AV人片一区二区密柚| 国产jizzjizz视频全部免费| 在线观看免费人成视频色9| 免费A级毛片无码视频| 成人免费av一区二区三区| 极品色天使在线婷婷天堂亚洲 | 亚洲熟女综合色一区二区三区 | 国产精品免费无遮挡无码永久视频| 久久精品国产亚洲av天美18| 亚洲天堂2017无码中文| 亚洲日产2021三区在线 | 国产婷婷成人久久Av免费高清| 狠狠综合亚洲综合亚洲色| 亚洲欧美不卡高清在线| 中文字幕乱码亚洲精品一区| 亚洲视频一区二区三区四区| 亚洲国产综合在线| 亚洲国产亚洲片在线观看播放| 亚洲电影在线播放| 亚洲第一成年人网站| 亚洲日本香蕉视频观看视频| 亚洲精品国产情侣av在线| 亚洲专区在线视频| 亚洲综合视频在线观看| 亚洲狠狠ady亚洲精品大秀| 亚洲一区二区三区电影| 日韩精品一区二区亚洲AV观看| 亚洲大成色www永久网站| 久久精品国产亚洲AV麻豆王友容 | xxxxx做受大片视频免费| 国产免费MV大全视频网站| 国产高潮久久免费观看| 搡女人免费免费视频观看| 国产午夜无码精品免费看| 99久久99热精品免费观看国产| 亚洲视频免费在线看| 成年女人毛片免费播放视频m|