日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java規(guī)則引擎的集成

 Jimmy Booker 2011-03-14

Java規(guī)則引擎的集成

 "本文摘自starrynght的blog星月夜,作者首先介紹了javarule,然后提供了spring和商務(wù)規(guī)則引擎的集成。

規(guī)則引擎簡(jiǎn)介
      Java規(guī)則引擎是推理引擎的一種,它起源于基于規(guī)則的專(zhuān)家系統(tǒng)。
      Java規(guī)則引擎將業(yè)務(wù)決策從應(yīng)用程序代碼中分離出來(lái),并使用預(yù)定義的語(yǔ)義模塊編寫(xiě)業(yè)務(wù)決策。Java規(guī)則引擎接受數(shù)據(jù)輸入,解釋業(yè)務(wù)規(guī)則,并根據(jù)規(guī)則作出業(yè)務(wù)決策。從這個(gè)意義上來(lái)說(shuō),它是軟件方法學(xué)在"關(guān)注點(diǎn)分離"上的一個(gè)重要的進(jìn)展。
      JSR-94規(guī)范定義了獨(dú)立于廠商的標(biāo)準(zhǔn)API,開(kāi)發(fā)人員可以通過(guò)這個(gè)標(biāo)準(zhǔn)的API使用Java規(guī)則引擎規(guī)范的不同產(chǎn)品實(shí)現(xiàn)。但值得注意的是,這個(gè)規(guī)范并沒(méi)有強(qiáng)制統(tǒng)一規(guī)則定義的語(yǔ)法,因此,當(dāng)需要將應(yīng)用移植到其他的Java規(guī)則引擎實(shí)現(xiàn)時(shí),可能需要變換規(guī)則定義。
 

基于規(guī)則的專(zhuān)家系統(tǒng)(RBES)
       專(zhuān)家系統(tǒng)是人工智能的一個(gè)分支,它模仿人類(lèi)的推理方式,使用試探性的方法進(jìn)行推理,并使用人類(lèi)能理解的術(shù)語(yǔ)解釋和證明它的推理結(jié)論。專(zhuān)家系統(tǒng)有很多分類(lèi):神經(jīng)網(wǎng)絡(luò)、基于案例推理和基于規(guī)則系統(tǒng)等。
       規(guī)則引擎則是基于規(guī)則的專(zhuān)家系統(tǒng)的一部分。為了更深入的了解Java規(guī)則引擎,下面簡(jiǎn)要地介紹基于規(guī)則的專(zhuān)家系統(tǒng)(RBES)。

  RBES的技術(shù)架構(gòu)
       RBES包括三部分:Rule Base(knowledge base)、Working Memory(fact base)和Rule Engine(推理引擎)。它們的結(jié)構(gòu)如下系統(tǒng)所示:
 

 
       如上圖所示,規(guī)則引擎包括三部分:Pattern Matcher、Agenda和Execution Engine。Pattern Matcher決定選擇執(zhí)行哪個(gè)規(guī)則,何時(shí)執(zhí)行規(guī)則;Agenda管理PatternMatcher挑選出來(lái)的規(guī)則的執(zhí)行次序;Execution Engine負(fù)責(zé)執(zhí)行規(guī)則和其他動(dòng)作。

  RBES的推理(規(guī)則)引擎
       和人類(lèi)的思維相對(duì)應(yīng),規(guī)則引擎存在兩者推理方式:演繹法(Forward-Chaining)和歸納法(Backward-Chaining)。演繹法從一個(gè)初始的事實(shí)出發(fā),不斷地應(yīng)用規(guī)則得出結(jié)論(或執(zhí)行指定的動(dòng)作)。而歸納法則是從假設(shè)出發(fā),不斷地尋找符合假設(shè)的事實(shí)。
       Rete算法是目前效率最高的一個(gè)Forward-Chaining推理算法,Drools項(xiàng)目是Rete算法的一個(gè)面向?qū)ο蟮腏ava實(shí)現(xiàn)。
       規(guī)則引擎的推理步驟如下:
       1. 將初始數(shù)據(jù)(fact)輸入Working Memory。
       2. 使用Pattern Matcher比較規(guī)則(rule)和數(shù)據(jù)(fact)。
       3. 如果執(zhí)行規(guī)則存在沖突(conflict),即同時(shí)激活了多個(gè)規(guī)則,將沖突的規(guī)則放入沖突集合。
       4. 解決沖突,將激活的規(guī)則按順序放入Agenda。
       5. 使用規(guī)則引擎執(zhí)行Agenda中的規(guī)則。重復(fù)步驟2至5,直到執(zhí)行完畢所有Agenda中的規(guī)則。

JSR 94:Java規(guī)則引擎API
       基于規(guī)則編程是一種聲明式的編程技術(shù),這種技術(shù)讓你可以使用試探性的規(guī)則而不是過(guò)程性的指令來(lái)解決問(wèn)題。規(guī)則引擎是一個(gè)軟件模塊,它決定了如何將規(guī)則作用于推理數(shù)據(jù)。在保險(xiǎn)業(yè)和金融服務(wù)業(yè)都廣泛地使用了基于規(guī)則的編程技術(shù),當(dāng)需要在大量的數(shù)據(jù)上應(yīng)用復(fù)雜的規(guī)則時(shí),規(guī)則引擎技術(shù)特別有用。
       Java規(guī)則引擎API由javax.rules包定義,是訪問(wèn)規(guī)則引擎的標(biāo)準(zhǔn)企業(yè)級(jí)API。Java規(guī)則引擎API允許客戶(hù)程序使用統(tǒng)一的方式和不同廠商的規(guī)則引擎產(chǎn)品交互,就像使用JDBC編寫(xiě)?yīng)毩⒂趶S商訪問(wèn)不同的數(shù)據(jù)庫(kù)產(chǎn)品一樣。Java規(guī)則引擎API包括創(chuàng)建和管理規(guī)則集合的機(jī)制,在Working Memory中添加,刪除和修改對(duì)象的機(jī)制,以及初始化,重置和執(zhí)行規(guī)則引擎的機(jī)制。

使用Java規(guī)則引擎API
       Java規(guī)則引擎API把和規(guī)則引擎的交互分為兩類(lèi):管理活動(dòng)和運(yùn)行時(shí)活動(dòng)。管理活動(dòng)包括實(shí)例化規(guī)則引擎和裝載規(guī)則。而運(yùn)行時(shí)活動(dòng)包括操作Working Memory和執(zhí)行規(guī)則。如果你在J2SE環(huán)境中使用Java規(guī)則引擎,你可能需要在代碼中執(zhí)行以上所有的活動(dòng)。相反,在J2EE環(huán)境中,Java規(guī)則引擎的管理活動(dòng)是應(yīng)用服務(wù)器的一部分。JSR 94的參考實(shí)現(xiàn)包括了一個(gè)JCA連接器,用于通過(guò)JNDI獲得一個(gè)RuleServiceProvider。

  設(shè)置規(guī)則引擎
       Java規(guī)則引擎的管理活動(dòng)階段開(kāi)始于查找一個(gè)合適的javax.rules.RuleServiceProvider對(duì)象,這個(gè)對(duì)象是應(yīng)用程序訪問(wèn)規(guī)則引擎的入口。在J2EE環(huán)境中,你可能可以通過(guò)JNDI獲得RuleServiceProvider。否則,你可以使用javax.rules.RuleServiceProviderManager類(lèi):
           javax.rules.RuleServiceProviderManager class:
           String implName = "org.jcp.jsr94.ri.RuleServiceProvider";
           Class.forName(implName);
           RuleServiceProvider serviceProvider = RuleServiceProviderManager.getRuleServiceProvider(implName);
       一旦擁有了RuleServiceProvider對(duì)象,你可以獲得一個(gè)javax.rules.admin.RuleAdministrator類(lèi)。從RuleAdministrator類(lèi)中,你可以得到一個(gè)RuleExecutionSetProvider,從類(lèi)名可以知道,它用于創(chuàng)建javax.rules.RuleExecutionSets對(duì)象。RuleExecutionSet基本上是一個(gè)裝入內(nèi)存的,準(zhǔn)備好執(zhí)行的規(guī)則集合。
       包javax.rules.admin包括兩個(gè)不同的RuleExecutionSetProvider類(lèi)。RuleExecutionSetProvider類(lèi)本身包括了從Serializable對(duì)象創(chuàng)建RuleExecutionSets的方法,因此在規(guī)則引擎位于遠(yuǎn)程服務(wù)器的情況下,仍然可以使用RuleExecutionSetProvider類(lèi),構(gòu)造器的參數(shù)可以通過(guò)RMI來(lái)傳遞。另一個(gè)類(lèi)是LocalRuleExecutionSetProvider,包含了其他方法,用于從非Serializable資源(如java.io.Reader-本地文件)創(chuàng)建RuleExectionSets。假設(shè)擁有了一個(gè)RuleServiceProvider對(duì)象,你可以從本地文件rules.xml文件創(chuàng)建一個(gè)RuleExectionSet對(duì)象。如以下的代碼所示:
          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();
          }
       接下來(lái),你可以使用RuleAdministrator注冊(cè)獲得的RuleExecutionSet,并給它分配一個(gè)名稱(chēng)。在運(yùn)行時(shí),你可以用同一個(gè)名稱(chēng)創(chuàng)建一個(gè)RuleSession;該RuleSession使用了這個(gè)命名的RuleExecutionSet。參見(jiàn)下面的例子:
admin.registerRuleExecutionSet("rules", ruleSet, properties);

  執(zhí)行規(guī)則引擎
       在運(yùn)行時(shí)階段,你可以參見(jiàn)一個(gè)RuleSession對(duì)象。RuleSession對(duì)象基本上是一個(gè)裝載了特定規(guī)則集合的規(guī)則引擎實(shí)例。你從RuleServiceProvider得到一個(gè)RuleRuntime對(duì)象,接下來(lái),從javax.rules.RuleRuntime得到RuleSession對(duì)象。
       RuleSession分為兩類(lèi):stateful和stateless。它們具有不同的功能。StatefulRuleSession的Working Memory能夠在多個(gè)方法調(diào)用期間保存狀態(tài)。你可以在多個(gè)方法調(diào)用期間在Working Memory中加入多個(gè)對(duì)象,然后執(zhí)行引擎,接下來(lái)還可以加入更多的對(duì)象并再次執(zhí)行引擎。相反,StatelessRuleSession類(lèi)是不保存狀態(tài)的,為了執(zhí)行它的executeRules方法,你必須為Working Memory提供所有的初始數(shù)據(jù),執(zhí)行規(guī)則引擎,得到一個(gè)內(nèi)容列表作為返回值。
       下面的例子中,我們創(chuàng)建一個(gè)StatefulRuleSession實(shí)例,添加兩個(gè)對(duì)象(一個(gè)Integer和一個(gè)String)到Working Memory,執(zhí)行規(guī)則,然后得到Working Memory中所有的內(nèi)容,作為java.util.List對(duì)象返回。最后,我們調(diào)用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();

集成JSR 94產(chǎn)品實(shí)現(xiàn)
       支持JSR 94規(guī)范的產(chǎn)品實(shí)現(xiàn)既有收費(fèi)的商業(yè)產(chǎn)品,也有免費(fèi)的開(kāi)源項(xiàng)目。目前最為成熟,功能最強(qiáng)大的商業(yè)產(chǎn)品是ILOG公司的JRules,該公司也是JSR 94規(guī)范的積極推動(dòng)者之一。支持JSR 94規(guī)范的開(kāi)源項(xiàng)目目前很少,只有Drools項(xiàng)目。值得注意的是,Jess不是開(kāi)源項(xiàng)目,它可以免費(fèi)用于學(xué)術(shù)研究,但用于商業(yè)用途則要收費(fèi)。

  JSR 94的產(chǎn)品實(shí)現(xiàn)
        Java規(guī)則引擎商業(yè)產(chǎn)品有:
           l. ILOG公司的JRules
          2. BlazeSoft公司的Blaze
          3. Rules4J
          4. Java Expert System Shell (JESS)
        開(kāi)源項(xiàng)目的實(shí)現(xiàn)包括:
          l. Drools項(xiàng)目
         2. OFBiz Rule Engine(不支持JSR 94)
         3. Mandarax(目前不支持JSR 94)

  使用Spring集成
       集成Java規(guī)則引擎的目標(biāo)是,使用標(biāo)準(zhǔn)的Java規(guī)則引擎API封裝不同的實(shí)現(xiàn),屏蔽不同的產(chǎn)品實(shí)現(xiàn)細(xì)節(jié)。這樣做的好處是,當(dāng)替換不同的規(guī)則引擎產(chǎn)品時(shí),可以不必修改應(yīng)用代碼。
    封裝JSR94實(shí)現(xiàn)
       RuleEngineFacade類(lèi)封裝Java規(guī)則引擎,使用ruleServiceProviderUrl和ruleServiceProviderImpl兩個(gè)參數(shù),屏蔽了不同產(chǎn)品的配置。代碼如下:
       public class RuleEngineFacade {
                private RuleAdministrator ruleAdministrator;
                private RuleServiceProvider ruleServiceProvider;
                private LocalRuleExecutionSetProvider ruleSetProvider;
                private RuleRuntime ruleRuntime;
                // configuration parameters
                private String ruleServiceProviderUrl;
                private Class ruleServiceProviderImpl;
 
          public void setRuleServiceProviderUrl(String url) {
                this.ruleServiceProviderUrl = url;
          }
           public void setRuleServiceProviderImpl(Class impl) {
                this.ruleServiceProviderImpl = impl;
          }
           public void init() throws Exception {
                RuleServiceProviderManager.registerRuleServiceProvider(
                ruleServiceProviderUrl, ruleServiceProviderImpl);
                ruleServiceProvider = RuleServiceProviderManager.getRuleServiceProvider(ruleServiceProviderUrl);
                ruleAdministrator = ruleServiceProvider.getRuleAdministrator();
                ruleSetProvider = ruleAdministrator.getLocalRuleExecutionSetProvider(null);
          }
          public void addRuleExecutionSet(String bindUri,InputStream resourceAsStream)
                    throws Exception {
                Reader ruleReader = new InputStreamReader(resourceAsStream);
                RuleExecutionSet ruleExecutionSet =
                ruleSetProvider.createRuleExecutionSet(ruleReader, null);
                ruleAdministrator.registerRuleExecutionSet(bindUri,ruleExecutionSet,null);
         }
         public StatelessRuleSession getStatelessRuleSession(String key)
                   throws Exception {
                ruleRuntime = ruleServiceProvider.getRuleRuntime();
                return (StatelessRuleSession) ruleRuntime.createRuleSession(key, null, RuleRuntime.STATELESS_SESSION_TYPE);
         }
         public StatefulRuleSession getStatefulRuleSession(String key)
                   throws Exception {
                ruleRuntime = ruleServiceProvider.getRuleRuntime();
                return (StatefulRuleSession) ruleRuntime.createRuleSession(
                key, null, RuleRuntime.STATEFUL_SESSION_TYPE);
         }
         public RuleServiceProvider getRuleServiceProvider() {
                return this.ruleServiceProvider;
         }
    }

    封裝規(guī)則
        Rule類(lèi)封裝了具體的業(yè)務(wù)規(guī)則,它的輸入?yún)?shù)ruleName是定義規(guī)則的配置文件名,并依賴(lài)于RuleEngineFacade組件。代碼如下:
    public class Rule {
         private String ruleName;
         private RuleEngineFacade engineFacade;
 
         public void init() throws Exception {
              InputStream is = Rule.class.getResourceAsStream(ruleName);
              engineFacade.addRuleExecutionSet(ruleName, is);
              is.close();
        }
 
        public void setRuleName(String name) {
             this.ruleName = name;
        }
 
        public void setEngineFacade(RuleEngineFacade engine) {
            this.engineFacade = engine;
        }
 
        public StatelessRuleSession getStatelessRuleSession()
                     throws Exception {
            return engineFacade.getStatelessRuleSession(ruleName);
        }
 
        public StatefulRuleSession getStatefuleRuleSession()
                     throws Exception {
            return engineFacade.getStatefulRuleSession(ruleName);
        }
    }

    組裝規(guī)則組件
       組裝規(guī)則的配置文件如下:

     
           http:///
     
      
           org.drools.jsr94.rules.RuleServiceProviderImpl
      


      
          /test/fibonacci.drl
     
      
          
     


    測(cè)試用例
       最后,我們編寫(xiě)測(cè)試用例,代碼如下:
public class JSRTest extends TestCase {
      ApplicationContext ctx = null;
      protected void setUp() throws Exception {
           super.setUp();
           ctx = new FileSystemXmlApplicationContext("testrule.xml");
      }
      public void testGetRuleSession() throws Exception {
           Rule rule = (Rule)ctx.getBean("fibonacci");
           assertNotNull(rule.getStatefuleRuleSession());
           assertNotNull(rule.getStatelessRuleSession());
      }
      public void testStatelessRule() throws Exception {
           Rule rule = (Rule)ctx.getBean("fibonacci");
           Fibonacci fibonacci = new Fibonacci(50);
           List list = new ArrayList();
           list.add(fibonacci);
           StatelessRuleSession session = rule.getStatelessRuleSession();
           session.executeRules(list);
           session.release();
      }
      public void testStatefulRule() throws Exception {
            Rule rule = (Rule)ctx.getBean("fibonacci");
            Fibonacci fibonacci = new Fibonacci(50);
            StatefulRuleSession session = rule.getStatefuleRuleSession();
            session.addObject(fibonacci);
            session.executeRules();
            session.release();
       }
}
 
       運(yùn)行測(cè)試用例,出現(xiàn)綠條,測(cè)試通過(guò)。

規(guī)則定義語(yǔ)言之間的變換
       因?yàn)镴SR 94規(guī)范并沒(méi)有強(qiáng)制統(tǒng)一規(guī)則定義的語(yǔ)法,因此,當(dāng)需要將應(yīng)用移植到其他的Java規(guī)則引擎實(shí)現(xiàn)時(shí),可能需要變換規(guī)則定義,如將Drools私有的DRL規(guī)則語(yǔ)言轉(zhuǎn)換成標(biāo)準(zhǔn)的ruleML,Jess規(guī)則語(yǔ)言轉(zhuǎn)換成ruleML等。這個(gè)工作一般由XSLT轉(zhuǎn)換器來(lái)完成。"

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多