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

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

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

    Junky's IT Notebook

    統(tǒng)計(jì)

    留言簿(8)

    積分與排名

    WebSphere Studio

    閱讀排行榜

    評論排行榜

    在你的企業(yè)級java應(yīng)用中使用Drools

    版權(quán)聲明:可以任意轉(zhuǎn)載,轉(zhuǎn)載時(shí)請務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
    原文地址:
    http://www.onjava.com/pub/a/onjava/2005/08/24/drools.html
    中文地址:
    http://www.matrix.org.cn/resource/article/43/43782_Drools.html
    關(guān)鍵詞: Drools J2ee


    什么是Drools
    (譯者增加:什么是Drools, 摘自drools.org)
    Drools 是一個(gè)基于Charles Forgy's的Rete算法的,專為Java語言所設(shè)計(jì)的規(guī)則引擎。Rete算法應(yīng)用于面向?qū)ο蟮慕涌趯⑹够谏虡I(yè)對象的商業(yè)規(guī)則的表達(dá)更為自然。Drools是用Java寫的,但能同時(shí)運(yùn)行在Java和.Net上。

    Drools
    Drools 被設(shè)計(jì)為可插入式的語言實(shí)現(xiàn)。目前規(guī)則能用Java, Python和Groovy實(shí)現(xiàn)。更為重要的是,Drools提供了聲明式程序設(shè)計(jì)(Declarative Programming),并且使用域描述語言(Domain Specific Languages (DSL))-專為你的問題域定義了某種模式的Xml, 它已經(jīng)足夠靈活到可以用來描述你的問題域。DSLs包含的XML元素(Element)和屬性(Attribute)代表了問題域中各種要素。

    (原文開始)
    這 段時(shí)間企業(yè)級Java簡直能讓你睡著。有多少J2EE-EJB應(yīng)用程序只是從網(wǎng)頁提取數(shù)據(jù)并把它們存入到數(shù)據(jù)庫中?但開發(fā)者真正應(yīng)該開發(fā)和維護(hù)的卻是他們 應(yīng)用程序中復(fù)雜的商業(yè)邏輯。這個(gè)問題不僅僅適用于將要新應(yīng)用,而且漸漸地,也適用于那些長期運(yùn)行的商業(yè)核心應(yīng)用,它們的內(nèi)部邏輯也需要經(jīng)常改變,而且往往 要求在一個(gè)非常短的時(shí)間內(nèi)。

    在以前的文章中,“用Drools讓你的商業(yè)邏輯使用框架”,我介紹了Drools框架,展示了它如何用來組 織復(fù)雜的商業(yè)邏輯。Drool用一組簡單的,眾所周知的事物替換了許多纏雜的if…then表達(dá)式。如果你經(jīng)歷過和商業(yè)客戶的會(huì)議,并為他們提出的想要實(shí) 現(xiàn)的東西的復(fù)雜程度搞得頭痛,或許你應(yīng)該考慮一下像Drools這樣的規(guī)則引擎了。這篇文章將向你展示如何在企業(yè)級Java應(yīng)用中使用Drools.

    一路到底的框架

    大 多數(shù)開發(fā)者都有自己喜愛的框架。無特定順序,它們包括表現(xiàn)層框架(Struts, JSF, Cocoon和Spring),持久化框架(JDO, Hibernate, Cayenne and Entity Beans)以及結(jié)構(gòu)框架(EJB, 又是Spring, Pico和Excalibur), 還有其它很多。每種框架都各有所長,給開發(fā)者提供子許多“即開即用”的功能。使用框架來部署應(yīng)用意味著你避免了許多讓人厭煩的細(xì)節(jié),讓你集中注意力到關(guān)鍵 之處。
    到目前為直,在框架所能做的事中仍然有一個(gè)缺口,那就是商業(yè)邏輯沒有框架。像EJB和Spring這樣的工具雖好,但它們卻幾乎沒有提及怎 么組織你的那些if …then語句。把Drools加到你的開發(fā)工具箱中意味著現(xiàn)在你可以“一路到底”的使用框架來構(gòu)建你的應(yīng)用程序。圖1顯示了這樣的一個(gè)應(yīng)用

    image
    圖1. 用于Java應(yīng)用的框架

    這篇文章將基于我們已經(jīng)了解的Drools框架的功能,這些功能可以讓我們構(gòu)建這樣的一個(gè)應(yīng)用。]

    我什么時(shí)候應(yīng)該使用規(guī)則引擎?
    “如果你有一把錘子,那所有的東西都看起來都像釘子”,這句話在軟件工程領(lǐng)域幾乎成了陳詞濫調(diào)了。雖然規(guī)則引擎能解決我們的許多問題,但確實(shí)值得認(rèn)真考慮一下規(guī)則引擎對我們的企業(yè)級Java應(yīng)用是否合適。需要問的問題有:

    我的應(yīng)用程序有多復(fù)雜?對于那些只是把數(shù)據(jù)從數(shù)據(jù)庫中傳入傳出,并不做更多事情的應(yīng)用程序,最好不要使用規(guī)則引擎。但是,當(dāng)在Java中有一定量的商業(yè)邏輯處理的話,可以考慮Drools的使用。這是因?yàn)楹芏鄳?yīng)用隨著時(shí)間的推移越來越復(fù)雜,而Drools可以讓你輕松應(yīng)對這一切。

    我的應(yīng)用的生命周期有多久?這個(gè)問題的正確答案往往是“令人驚訝的長”――還記得那些認(rèn)為他們的程序不會(huì)茍活到2000年的大型機(jī)的程序員嗎?使用規(guī)則引擎將會(huì)在中長期得到好處。像這篇文章所展示的那樣,甚至原型都能從Drools與靈活方法的組合中獲益,讓“原型系統(tǒng)”轉(zhuǎn)化成生產(chǎn)系統(tǒng)。

    我的應(yīng)用需要改變嗎?唯一能確定的是你的需求將會(huì)改變,無論是在開發(fā)過程中或是在開發(fā)完成以后。Drools使用一個(gè)或多個(gè)簡單易配的XML文件幫你來應(yīng)對這一切。

    那么性能呢?
    如 果你正在寫一個(gè)企業(yè)級應(yīng)用,很有可能它會(huì)擴(kuò)展到成百(如果不是成千)的用戶。你已經(jīng)知道現(xiàn)有的Java和J2EE應(yīng)用能做到這一點(diǎn),但一個(gè)使用了 Drools的應(yīng)用對這一壓力的表現(xiàn)如何?答案是:“令人吃驚的好”。大多數(shù)開發(fā)者只是因?yàn)椴辉?#8220;失控”而依賴于他人的代碼(比如:某種框架),想想這 個(gè):Drools不僅可以讓你的應(yīng)用和“傳統(tǒng)”的編程方法一樣快,甚至可以更快,看下面:

    避免糟糕的代碼:Drools引導(dǎo)開發(fā)者去做“正確的事”。你可以確定你正在寫的代碼是好的,但你的開發(fā)伙伴呢?你可以同樣這樣說嗎?使用框架可以讓你更輕松地寫出更快,更好的代碼。

    優(yōu)化過的框架:你有多少次看見商業(yè)邏輯重復(fù)地從數(shù)據(jù)庫中提取相同的信息,從而降低了整個(gè)應(yīng)用的速度?如果正確使用的話,Drools不僅僅能夠記住信息,而且還能記住以往使用該信息進(jìn)行測試的結(jié)果,從而大幅提升應(yīng)用的速度。

    Rete算法: 很多次我們并不是真正需要使用“if”條件。被Drools實(shí)現(xiàn)的Rete算法,可以用一個(gè)優(yōu)化的方法替換掉所有的“if…then”表達(dá)式。需要重點(diǎn)提 及的是:Rete算法在使用更多的內(nèi)存來降低運(yùn)行時(shí)延遲方面作了折衷。當(dāng)然這在現(xiàn)代的應(yīng)用服務(wù)器中并不是一個(gè)問題,我們也并不推薦你在移動(dòng)手機(jī)上使用 Drools!

    我們到哪里了?

    在 我們上一篇文章中,我們寫了一個(gè)基于Drools引擎的簡單的股票交易程序。我們實(shí)現(xiàn)了不同的商業(yè)規(guī)則,展示了我們可以如何迅速地改變規(guī)則去適應(yīng)商業(yè)需 求,并且JUnit測試給了我們高度自信可以確認(rèn)系統(tǒng)確實(shí)是像我們設(shè)想的那樣運(yùn)作的。但是這個(gè)應(yīng)用幾乎沒有用戶介面,而且用硬編碼代替了數(shù)據(jù)庫。為了把我 們的程序提升到企業(yè)級的水平,我們需要增加兩個(gè)主要的東西。

    ● 某種用戶介面,最理想的是基于標(biāo)準(zhǔn)的Web表現(xiàn)層的框架。
    ● 一個(gè)數(shù)據(jù)存取對象(DAO)讓Drools與數(shù)據(jù)庫(或其它后端)交互。

    從現(xiàn)有表現(xiàn)框架中實(shí)現(xiàn)規(guī)則引擎

    大 多數(shù)企業(yè)級Java應(yīng)用是通過Web介面進(jìn)行交互的,其中最被廣泛使用的Web表現(xiàn)層框架是Apache的Struts。理想的結(jié)果是:我們寫的應(yīng)用可以 從表現(xiàn)層知道它下面的應(yīng)用層,而不是通過相反的方向。它的好處在于不僅僅可以使我們將來變換其它的表現(xiàn)層(比如Ajax或web service界面),而且意味著示例代碼可以非常容易地應(yīng)用于其它像Spring的框架。

    下面的代碼片斷演示了始何從Web表現(xiàn)層調(diào)用 商業(yè)邏輯(通過規(guī)則引擎),并根據(jù)返回結(jié)果顯示不同的頁面。這一例子中,我們使用了一個(gè)Struts行為,但其代碼是和使用其它表現(xiàn)層框架甚至一個(gè) Servlet或一個(gè)Jsp頁面是很類似的。這個(gè)片斷使用了struts-config.xml配置文件,JSP頁面來上傳/顯示數(shù)據(jù),并且生成WAR文 件來進(jìn)行布署。片斷展示了怎樣把規(guī)則引擎和web框架集成使用。

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.struts.action.Action;
    import org.apache.struts.action.ActionForm;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.ActionMapping;
    import BusinessLayer;
    /**
    * Sample Struts action with Pseudocode
    * 使用偽代碼的Struts行為示例
    */
    public class SampleStrutsAction extends Action{
          
      /**
       * Standard Struts doPerfom method
       * 標(biāo)準(zhǔn)的Struts doPerform方法
       */
      public ActionForward doPerform(
                    ActionMapping mapping,
                        ActionForm form,
                        HttpServletRequest request,
                        HttpServletResponse response)
            throws InvalidEntryPointException {
    //Local Variables
    //本地變量
        StockOffer userOffer =null;
            
    //Get any previous values from the session
    //從session取得以前的數(shù)據(jù)
        userOffer=(StockOffer)request.getSession()
               .getAttribute("PREVIOUS_STOCK_OFFER");
                    
    //create this object if it is null
    //如為null則創(chuàng)建新對象
        if (null==userOffer){
          userOffer = new StockOffer();
        }
    //Update with the incoming values
    //用上送的數(shù)據(jù)更新
    //These values match those on the form      
    //這些數(shù)據(jù)是與form中的數(shù)據(jù)相對應(yīng)的
        userOffer.setStockName(request.
                    getParameterValue("STOCK_NAME"));
        userOffer.setStockPrice(request
                   .getParameterValue("STOCK_PRICE"));
        userOffer.setStockQuantity(request
                   .getParameterValue("STOCK_QTY"));
                                    
    //Reset the output value
    //重置輸出數(shù)據(jù)
        userOffer.setRecommendPurchase(null);
    //Call the Business Layer
    //調(diào)用商業(yè)層
        BusinessLayer
                  .evaluateStockPurchase(userOffer);        
                    
    //Forward to the appropriate page
    //轉(zhuǎn)向合適的頁面
        if ("YES".equals(
          testOffer.getRecommendPurchase()){
            return mapping.findForward("YES_WEB_PAGE");
        }
    //otherwise default to the no page
    //否則指向無此頁面
              return mapping.findForward("NO_WEB_PAGE");
      }
    }


    這個(gè)例子包含了幾個(gè)東西。經(jīng)常,我們需要的數(shù)據(jù)是用戶通過好幾個(gè)網(wǎng)頁傳來的,因此在這一例子中展示了通過session中的StockOffer對象來保存過去以來的數(shù)據(jù)。

    下一步,如果用戶改變了一些值,我們更新StockOffer對象。然后我們重置了rcommendPurchase標(biāo)志用以在調(diào)用商業(yè)邏輯層之前清除以前的結(jié)果。最后我們使用商業(yè)邏輯層的返回來決定讓用戶轉(zhuǎn)向哪一頁面。

    在 這一例子中,需要注意我們將商業(yè)邏輯(買或不買一支股票)與表現(xiàn)層邏輯(決定轉(zhuǎn)向哪一頁面)分離開來。這將使我們可以在不同的應(yīng)用中重用我們的商業(yè)規(guī)則。 另外,看一下狀態(tài)信息(用戶已經(jīng)告知我們的東西)是存儲在Session中的StockOffer對象中的,并沒有在商業(yè)層中。這樣就保證了商業(yè)層的無狀 態(tài)性,這將使整個(gè)應(yīng)用更具擴(kuò)展性和性能。

    集成規(guī)則引擎與數(shù)據(jù)庫層

    到 目前為止,我們的應(yīng)用已經(jīng)有一個(gè)web表現(xiàn)層和一個(gè)商業(yè)層的規(guī)則引擎,但還沒有方法與數(shù)據(jù)庫進(jìn)行交互。這一節(jié)的例子將展示如何實(shí)現(xiàn)。我們的例子是基于數(shù)據(jù) 訪問對象(DAO)模式的,它把所有與數(shù)據(jù)庫(或后端數(shù)據(jù)源)交互的代碼包裝在了一個(gè)可插入,可配置的類中。同樣的,這一例子一樣適用于其它持久性框  架,比如Hibernate和Cayenne。
    關(guān)于如何組織數(shù)據(jù)導(dǎo)有幾個(gè)要點(diǎn):

    ● 應(yīng)該只有商業(yè)層與數(shù)據(jù)層交互。如果表現(xiàn)層(前端)需要一些數(shù)據(jù),它首先應(yīng)通過商業(yè)層。這將使我們的代碼更容易組織和閱讀。
    ● 盡可能地,我們應(yīng)讓我們的數(shù)據(jù)層無狀態(tài)-我們應(yīng)該在其它的地方存放客戶端數(shù)據(jù)(比如:web前端的session,就像前面的例子)。這不同于我們可以在 這一層做的數(shù)據(jù)緩存。兩者的區(qū)別在于狀態(tài)信息經(jīng)常是用戶定義的,而我們在數(shù)據(jù)層緩存的數(shù)據(jù)應(yīng)該是整個(gè)應(yīng)用共享的。這樣的層次提升了性能。
    ● 我們應(yīng)該讓商業(yè)邏輯決定數(shù)據(jù)是否需要――如不需要,提取數(shù)據(jù)的調(diào)用就不應(yīng)該執(zhí)行。

    為了實(shí)現(xiàn)我們簡單的數(shù)據(jù)訪問對象,我們創(chuàng)建三個(gè)新對象:StockNameDao, DaoImplementation,和 DaoFactory

    StockNameDao是一個(gè)定義了兩個(gè)方法的接口:getStockName()返回一個(gè)我們可以處理的股票名稱的列表,isOnStockList()檢查一個(gè)給定的股票是否在處理列表中。我們的商業(yè)層在需要這些信息時(shí)會(huì)調(diào)用這些方法。

    DaoImplementation是StockNameDao的一個(gè)實(shí)現(xiàn)。這里的數(shù)據(jù)是硬編碼的,但我們可以通過查詢數(shù)據(jù)庫或通過像Bloomberg這樣的web service提取信息。

    DaoFactory 我們用來生成合適的StockNameDao實(shí)例。不直接創(chuàng)建對象而使用這一小驟的好處在于,它充許我們在運(yùn)行時(shí)刻決定使用哪一個(gè)DAO實(shí)現(xiàn)(這是像 Spring這樣的框架特別擅長的).一個(gè)factory(工廠)可以返回多種類型的DAO(比如:StockNameDao, StockPriceDao, StockHistoryDao),這意味著我們可以通過我們的DaoFactory,讓規(guī)則自己決定需要什么數(shù)據(jù)和DAO.

    這是StockNameDao接口:

    /**
    * Defines a Data Access Object - a non data
    * source specific way of obtaining data.
    * 定義一個(gè)數(shù)據(jù)存取對象-一種非數(shù)據(jù)源獲取數(shù)據(jù)的方法
    */
    public interface StockNameDao {
      /**
       * Get a list of stock names for the application
       * @return String[] array of stock names
       * 得到一個(gè)股票名字的列表
       * 返回股票名稱的String[]數(shù)組
       */
      public String [] getStockNames();
            
      /**
       * Check if our stock is on the list
       * 檢查股票是否在列表中
       * @param stockName
       * @return
       */
      public boolean isOnStockList(String stockName);
    }
    And here's the DaoImplementation:
    這是DaoImplementation:

    /**
    * Concrete Definition of a Data Access Object
    * 數(shù)據(jù)存取對象的具體定義
    */
    public class DaoImplementation
                            implements StockNameDao {
      /**
       * Constructor with package level access only
       * to encourage use of factory method
       * 這里的構(gòu)造器只是讓你使用工廠(factory)方法
       */
      DaoImplementation(){}
      /**
       * Get a list of stock names for the app.
       * This is a hard coded sample
       * normally we would get this from
       * a database or other datasource.
       * 得到一個(gè)股票名字的列表,這只是一個(gè)硬編碼的例子,一般來
      * 說我們應(yīng)該從數(shù)據(jù)庫或其它數(shù)據(jù)源取得數(shù)據(jù)
       * @return String[] array of stock names
       */
      public String[] getStockNames() {
        String[] stockNames=
          {"XYZ","ABC","MEGACORP","SOMEOTHERCOMPANY"};
      
        return stockNames;
      }
            
      /**
       * Check if our stock is on the list
       * 檢查我們的股票是否在列表中
       * @param stockName
       * @return true / false as appropriate
       */
      public boolean isOnStockList(String stockName){
                    
    //Get our list of stocks  
    //獲取股票列表          
        String stockList[] = getStockNames();
                    
        //Loop and see if our stock is on it
    // done this way for clarity . not speed!
    //循環(huán)看股票是否存在,這樣做是為了清晰不是速度!
        for (int a=0; a<stockList.length;a++){
            if(stockList[a].equals(stockName)){
              return true;
            }
        }
                    
        //Default return value
        return false;      
      }
    }


    簡單的DaoFactory,只是返回DaoImplementation:

    package net.firstpartners.rp;
    /**
    * Factory Method to get the Data Access Object.
    * Normally we could replace this with a
    * framework like Spring or Hibernate
    * 得到數(shù)據(jù)存取對象的工廠方法,通常我們可以將它替換為像Spring或
    *  Hibernatte這樣的框架
    */
    public class DaoFactory {
      /**
       * Get the stock name Dao
       * This sample is hardcoded - in reality
       * we would make this configurable / cache
       * instances of the Dao as appropriate
       * 得到股票名字的Dao,這個(gè)例子是硬編碼的-實(shí)際上我們可以讓它成為
      * 可配的,緩存的合適的Dao對象。
       * @return an instance of StockNameDao
       */
      public static StockNameDao getStockDao(){
            return new DaoImplementation();
      }
    }


    現(xiàn)在我們有了簡單的DAO實(shí)現(xiàn)來作為我們的數(shù)據(jù)庫層,那如何將它與Drools商業(yè)層集成在一起呢?最新的商業(yè)規(guī)則文件,BusinessLayer.xml將會(huì)向我們展示:

    <?xml version="1.0"?>
    <rule-set name="BusinessRulesSample"
      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 the Java Objects that
                            we refer to in our rules -->
    <!-- 導(dǎo)入規(guī)則中使用的對象 -->
      <java:import>
        java.lang.Object
      </java:import>
      <java:import>
        java.lang.String
      </java:import>
      <java:import>
        net.firstpartners.rp.StockOffer
      </java:import>
      <java:import>
        net.firstpartners.rp.DaoFactory
      </java:import>
      <java:import>
        net.firstpartners.rp.StockNameDao
      </java:import>
      <!-- Application Data not associated -->
      <!-- with any particular rule -->
      <!-- In this case it's our factory -->
      <!-- object which gives us back -->
      <!-- a handle to whatever Dao (Data -->
      <!-- access object) that we need -->
      <!-- 沒有和任何規(guī)則聯(lián)系的應(yīng)用數(shù)據(jù),這里是我們的工廠對象,-->
      <!—它向我們提供向后的操作,告訴我們什么Dao 是我們需要的。-->

      <application-data
        identifier="daoFactory">DaoFactory
      </application-data>
      <!-- A Java (Utility) function -->
    <!-- 一個(gè)Java方法 -->
      <!-- we reference in our rules -->  
      <!-- 在我們的規(guī)則中打印跟蹤信息 -->    
      <java:functions>
        public void printStock(
          net.firstpartners.rp.StockOffer stock)
          {
              System.out.println(
              "Name:"+stock.getStockName()
              +" Price: "+stock.getStockPrice()    
              +" BUY:"+stock.getRecommendPurchase());
          }
      </java:functions>
      <!-- Check for XYZ Corp-->  
    <!-- 檢查XYZ公司 -->    
      <rule name="XYZCorp" salience="-1">
        <!-- Parameters we can pass into-->
    <!-- the business rule -->
    <!-- 可以傳入規(guī)則中的參數(shù) -->
        <parameter identifier="stockOffer">
          <class>StockOffer</class>
        </parameter">
        <!-- Conditions that must be met for -->
    <!-- business rule to fire -->  
    <!-- 激活規(guī)則必須滿足的條件 -->      
        <java:condition>
          stockOffer.getStockName().equals("XYZ")
        </java:condition>
        <java:condition>
          stockOffer.getRecommendPurchase() == null
        </java:condition>
        <java:condition>
          stockOffer.getStockPrice() > 10
        </java:condition>
            
        <!-- What happens when the business -->
    <!-- rule is activated -->
    <!-- 規(guī)則激活后執(zhí)行的步驟 -->
        <java:consequence>
            stockOffer.setRecommendPurchase(
            StockOffer.NO);
            printStock(stockOffer);
        </java:consequence>
      </rule>
      <!-- Ensure that negative prices -->
      <!-- are not accepted -->  
      <!-- 確定負(fù)數(shù)不被接受 -->    
      <rule name="Stock Price Not Negative">
        <!-- Parameters we can pass into the -->
    <!-- business rule -->
    <!-- 可以傳入規(guī)則中的參數(shù) -->  
        <parameter identifier="stockOffer">
          <class>StockOffer</class>
        </parameter>
    <!-- Conditions for rule to fire -->
    <!-- 激活規(guī)則必須滿足的條件 -->    
        <java:condition>
          stockOffer.getStockPrice() < 0
        </java:condition>
      
    <!--When rule is activated then ... -->
    <!-- 規(guī)則激活后執(zhí)行的步驟 -->
        <java:consequence>
          stockOffer.setRecommendPurchase
            (StockOffer.NO);        
          printStock(stockOffer);
        </java:consequence>
      </rule>
      <!-- Check for Negative Prices-->  
    <!-- 尋找低價(jià) -->    
      <rule name="Stock Price Low Enough">
      <!-- Parameters for the rule -->
    <!-- 可以傳入規(guī)則中的參數(shù) -->
        <parameter identifier="stockOffer">
          <class>StockOffer</class>
        </parameter>
        
    <!-- Now uses Dao to get stock list -->
    <!-- 現(xiàn)在使用Dao獲取股票列表 -->
        <java:condition>
          daoFactory.getStockDao().isOnStockList(
            stockOffer.getStockName())
        </java:condition>
            
        <java:condition>
          stockOffer.getRecommendPurchase() == null
        </java:condition>
        <java:condition>
          stockOffer.getStockPrice() < 100
        </java:condition>
    <!-- When rule is activated do this -->
    <!-- 規(guī)則激活后執(zhí)行的步驟 -->
        <java:consequence>
            stockOffer.setRecommendPurchase(
              StockOffer.YES);      
              printStock(stockOffer);
        </java:consequence>
      </rule>
    </rule-set>


    為了與數(shù)據(jù)訪問層集成,該文件(相對于上一篇文章)有幾處改變:
    ● 在最上面,我們有幾個(gè)新的<java:import>來把StockNameDao, DaoImplementation, 和 DaoFactory類引入系統(tǒng)。
    ● 我們有一個(gè)新的標(biāo)記<application-data>,它把DaoFactory的實(shí)例賦給一個(gè)變量。<application-data>標(biāo)記類似于參數(shù),只不過它是運(yùn)用于所有商業(yè)規(guī)則,而不只是一個(gè)。
    ● “股價(jià)足夠低”的規(guī)則有一個(gè)新條件,它用DaoFactory和StockNameDao來檢查股票是否在處理列表中。

    我 們又一次運(yùn)行BusinessRulesTest(模擬器)。模擬單元測試沒有問題,既使我們改變了程序的結(jié)構(gòu),我們?nèi)匀粵]有改變它在做什么。從輸出的日 志來看,我們可以看到我們的商業(yè)規(guī)則使用StockNameDao作為他們評估的一部份,并且 DaoImplementation.isOnStockList()被調(diào)用了。
    雖然這個(gè)例子展示的是從數(shù)據(jù)源讀取信息,其實(shí)寫信息也是一樣的原 理。如果某個(gè)規(guī)則決定應(yīng)該做的話。區(qū)別在于我們的DAO將會(huì)有一些setSomeInformation()的方法,一旦條件滿足,這個(gè)方法將會(huì)在商業(yè)規(guī) 則的<java:consequence>部分被調(diào)用。

    總結(jié)
    這 篇文章中,我們展示了大多數(shù)Java服務(wù)器端的應(yīng)用有的三層:表現(xiàn)層,商業(yè)邏輯層和數(shù)據(jù)持久化層。當(dāng)框架被廣泛地使用在表現(xiàn)層和持久層中,直到目前為止還 沒有框架可以包裝低級的商業(yè)邏輯。就像我們在這些例子中看的,Drools和JSR-94是降低java應(yīng)用復(fù)雜度,提高開發(fā)速度的理想候選者。我希望這 些例程能鼓勵(lì)你去進(jìn)一步接近規(guī)則引擎,他們將會(huì)為你的應(yīng)用的開發(fā)和維護(hù)節(jié)省不少時(shí)間。
    資源
    本文的范例代碼
    Drools項(xiàng)目主頁
    ● [ur=http://www.jroller.com/page/eu/20040810]Drools規(guī)則的信息[/url]
    "Introduction to Drools and Rule Engines," Drools項(xiàng)目組提供
    Drools規(guī)則的schema文件
    JSR-94: Java規(guī)則引擎概述
    Struts框架主頁
    Spring框架主頁
    Hibernate主頁
    JUnit測試框架

    ● [url=http://herzberg.ca.sandia.gov/jess/index.shtml]Jena語義與規(guī)則引擎

    JSR-94主頁
    Jess in Action主頁
    "Business Rule Thinking" (基于Jess)
    規(guī)則系統(tǒng)的概述
    "Jess implementation of the Rete algorithm"

    Paul Browne 已經(jīng)為 FirstPartners.net在企業(yè)級Java應(yīng)用方面作了差不多7年的顧問  

    posted on 2007-06-27 18:09 junky 閱讀(351) 評論(0)  編輯  收藏 所屬分類: 規(guī)則引擎


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 日本黄色动图免费在线观看| 性xxxxx免费视频播放| 亚洲日韩国产一区二区三区在线| 久久精品国产精品亚洲艾草网美妙| 国产成人无码免费看视频软件| 日韩毛片免费在线观看| 亚洲乱码一区av春药高潮| 亚洲av永久无码精品秋霞电影影院 | 亚洲AV综合色一区二区三区| 免费国产成人高清视频网站| 毛片基地免费视频a| 精品国产污污免费网站aⅴ| 精品97国产免费人成视频 | 日本黄色免费观看| 亚洲毛片在线免费观看| 国产成人AV片无码免费| 久久久精品国产亚洲成人满18免费网站| 成人精品国产亚洲欧洲| 亚洲影院天堂中文av色| 亚洲国产精品免费观看| 在线观看免费国产视频| 欧美男同gv免费网站观看| 222www免费视频| 在线人成精品免费视频| 国产精品免费一区二区三区四区| 久久久久女教师免费一区| 国产精品免费久久| 七次郎成人免费线路视频| 日本在线观看免费高清| 永久免费观看黄网站| 日韩毛片一区视频免费| 一级毛片免费播放视频| 美女内射无套日韩免费播放| 永久免费av无码网站yy| 精品免费视在线观看| 三年片在线观看免费观看大全动漫| 国产免费一区二区三区不卡| 久久国产精品2020免费m3u8 | 一本色道久久综合亚洲精品| 精品国产香蕉伊思人在线在线亚洲一区二区 | 亚洲色一色噜一噜噜噜|