文章詳情頁(yè)
在你的企業(yè)級(jí)java應(yīng)用中使用Drools
瀏覽:82日期:2024-06-12 18:21:33
內(nèi)容: 在你的企業(yè)級(jí)java應(yīng)用中使用Drools作者:Paul Browne08/24/2005 翻譯:simmone版權(quán)聲明:可以任意轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(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語(yǔ)言所設(shè)計(jì)的規(guī)則引擎。Rete算法應(yīng)用于面向?qū)ο蟮慕涌趯⑹够谏虡I(yè)對(duì)象的商業(yè)規(guī)則的表達(dá)更為自然。Drools是用Java寫的,但能同時(shí)運(yùn)行在Java和.Net上。DroolsDrools 被設(shè)計(jì)為可插入式的語(yǔ)言實(shí)現(xiàn)。目前規(guī)則能用Java, Python和Groovy實(shí)現(xiàn)。更為重要的是,Drools提供了聲明式程序設(shè)計(jì)(Declarative Programming),并且使用域描述語(yǔ)言(Domain Specific Languages (DSL))-專為你的問(wèn)題域定義了某種模式的Xml, 它已經(jīng)足夠靈活到可以用來(lái)描述你的問(wèn)題域。DSLs包含的XML元素(Element)和屬性(Attribute)代表了問(wèn)題域中各種要素。(原文開始)這段時(shí)間企業(yè)級(jí)Java簡(jiǎn)直能讓你睡著。有多少J2EE-EJB應(yīng)用程序只是從網(wǎng)頁(yè)提取數(shù)據(jù)并把它們存入到數(shù)據(jù)庫(kù)中?但開發(fā)者真正應(yīng)該開發(fā)和維護(hù)的卻是他們應(yīng)用程序中復(fù)雜的商業(yè)邏輯。這個(gè)問(wèn)題不僅僅適用于將要新應(yīng)用,而且漸漸地,也適用于那些長(zhǎng)期運(yùn)行的商業(yè)核心應(yīng)用,它們的內(nèi)部邏輯也需要經(jīng)常改變,而且往往要求在一個(gè)非常短的時(shí)間內(nèi)。在以前的文章中,“用Drools讓你的商業(yè)邏輯使用框架,我介紹了Drools框架,展示了它如何用來(lái)組織復(fù)雜的商業(yè)邏輯。Drool用一組簡(jiǎn)單的,眾所周知的事物替換了許多纏雜的if…then表達(dá)式。如果你經(jīng)歷過(guò)和商業(yè)客戶的會(huì)議,并為他們提出的想要實(shí)現(xiàn)的東西的復(fù)雜程度搞得頭痛,或許你應(yīng)該考慮一下像Drools這樣的規(guī)則引擎了。這篇文章將向你展示如何在企業(yè)級(jí)Java應(yīng)用中使用Drools.一路到底的框架大多數(shù)開發(fā)者都有自己喜愛的框架。無(wú)特定順序,它們包括表現(xiàn)層框架(Struts, JSF, Cocoon和Spring),持久化框架(JDO, Hibernate, Cayenne and Entity Beans)以及結(jié)構(gòu)框架(EJB, 又是Spring, Pico和Excalibur), 還有其它很多。每種框架都各有所長(zhǎng),給開發(fā)者提供子許多“即開即用的功能。使用框架來(lái)部署應(yīng)用意味著你避免了許多讓人厭煩的細(xì)節(jié),讓你集中注意力到關(guān)鍵之處。到目前為直,在框架所能做的事中仍然有一個(gè)缺口,那就是商業(yè)邏輯沒(méi)有框架。像EJB和Spring這樣的工具雖好,但它們卻幾乎沒(méi)有提及怎么組織你的那些if …then語(yǔ)句。把Drools加到你的開發(fā)工具箱中意味著現(xiàn)在你可以“一路到底的使用框架來(lái)構(gòu)建你的應(yīng)用程序。圖1顯示了這樣的一個(gè)應(yīng)用 圖1. 用于Java應(yīng)用的框架這篇文章將基于我們已經(jīng)了解的Drools框架的功能,這些功能可以讓我們構(gòu)建這樣的一個(gè)應(yīng)用。]我什么時(shí)候應(yīng)該使用規(guī)則引擎?“如果你有一把錘子,那所有的東西都看起來(lái)都像釘子,這句話在軟件工程領(lǐng)域幾乎成了陳詞濫調(diào)了。雖然規(guī)則引擎能解決我們的許多問(wèn)題,但確實(shí)值得認(rèn)真考慮一下規(guī)則引擎對(duì)我們的企業(yè)級(jí)Java應(yīng)用是否合適。需要問(wèn)的問(wèn)題有:● 我的應(yīng)用程序有多復(fù)雜?對(duì)于那些只是把數(shù)據(jù)從數(shù)據(jù)庫(kù)中傳入傳出,并不做更多事情的應(yīng)用程序,最好不要使用規(guī)則引擎。但是,當(dāng)在Java中有一定量的商業(yè)邏輯處理的話,可以考慮Drools的使用。這是因?yàn)楹芏鄳?yīng)用隨著時(shí)間的推移越來(lái)越復(fù)雜,而Drools可以讓你輕松應(yīng)對(duì)這一切。● 我的應(yīng)用的生命周期有多久?這個(gè)問(wèn)題的正確答案往往是“令人驚訝的長(zhǎng)――還記得那些認(rèn)為他們的程序不會(huì)茍活到2000年的大型機(jī)的程序員嗎?使用規(guī)則引擎將會(huì)在中長(zhǎng)期得到好處。像這篇文章所展示的那樣,甚至原型都能從Drools與靈活方法的組合中獲益,讓“原型系統(tǒng)轉(zhuǎn)化成生產(chǎn)系統(tǒng)。● 我的應(yīng)用需要改變嗎?唯一能確定的是你的需求將會(huì)改變,無(wú)論是在開發(fā)過(guò)程中或是在開發(fā)完成以后。Drools使用一個(gè)或多個(gè)簡(jiǎn)單易配的XML文件幫你來(lái)應(yīng)對(duì)這一切。那么性能呢?如果你正在寫一個(gè)企業(yè)級(jí)應(yīng)用,很有可能它會(huì)擴(kuò)展到成百(如果不是成千)的用戶。你已經(jīng)知道現(xiàn)有的Java和J2EE應(yīng)用能做到這一點(diǎn),但一個(gè)使用了Drools的應(yīng)用對(duì)這一壓力的表現(xiàn)如何?答案是:“令人吃驚的好。大多數(shù)開發(fā)者只是因?yàn)椴辉?ldquo;失控而依賴于他人的代碼(比如:某種框架),想想這個(gè):Drools不僅可以讓你的應(yīng)用和“傳統(tǒng)的編程方法一樣快,甚至可以更快,看下面:● 避免糟糕的代碼:Drools引導(dǎo)開發(fā)者去做“正確的事。你可以確定你正在寫的代碼是好的,但你的開發(fā)伙伴呢?你可以同樣這樣說(shuō)嗎?使用框架可以讓你更輕松地寫出更快,更好的代碼。● 優(yōu)化過(guò)的框架:你有多少次看見商業(yè)邏輯重復(fù)地從數(shù)據(jù)庫(kù)中提取相同的信息,從而降低了整個(gè)應(yīng)用的速度?如果正確使用的話,Drools不僅僅能夠記住信息,而且還能記住以往使用該信息進(jìn)行測(cè)試的結(jié)果,從而大幅提升應(yīng)用的速度。● Rete算法:很多次我們并不是真正需要使用“if條件。被Drools實(shí)現(xiàn)的Rete算法,可以用一個(gè)優(yōu)化的方法替換掉所有的“if…then表達(dá)式。需要重點(diǎn)提及的是:Rete算法在使用更多的內(nèi)存來(lái)降低運(yùn)行時(shí)延遲方面作了折衷。當(dāng)然這在現(xiàn)代的應(yīng)用服務(wù)器中并不是一個(gè)問(wèn)題,我們也并不推薦你在移動(dòng)手機(jī)上使用Drools!我們到哪里了?在我們上一篇文章中,我們寫了一個(gè)基于Drools引擎的簡(jiǎn)單的股票交易程序。我們實(shí)現(xiàn)了不同的商業(yè)規(guī)則,展示了我們可以如何迅速地改變規(guī)則去適應(yīng)商業(yè)需求,并且JUnit測(cè)試給了我們高度自信可以確認(rèn)系統(tǒng)確實(shí)是像我們?cè)O(shè)想的那樣運(yùn)作的。但是這個(gè)應(yīng)用幾乎沒(méi)有用戶介面,而且用硬編碼代替了數(shù)據(jù)庫(kù)。為了把我們的程序提升到企業(yè)級(jí)的水平,我們需要增加兩個(gè)主要的東西。● 某種用戶介面,最理想的是基于標(biāo)準(zhǔn)的Web表現(xiàn)層的框架。● 一個(gè)數(shù)據(jù)存取對(duì)象(DAO)讓Drools與數(shù)據(jù)庫(kù)(或其它后端)交互。從現(xiàn)有表現(xiàn)框架中實(shí)現(xiàn)規(guī)則引擎大多數(shù)企業(yè)級(jí)Java應(yīng)用是通過(guò)Web介面進(jìn)行交互的,其中最被廣泛使用的Web表現(xiàn)層框架是Apache的Struts。理想的結(jié)果是:我們寫的應(yīng)用可以從表現(xiàn)層知道它下面的應(yīng)用層,而不是通過(guò)相反的方向。它的好處在于不僅僅可以使我們將來(lái)變換其它的表現(xiàn)層(比如Ajax或web service界面),而且意味著示例代碼可以非常容易地應(yīng)用于其它像Spring的框架。下面的代碼片斷演示了始何從Web表現(xiàn)層調(diào)用商業(yè)邏輯(通過(guò)規(guī)則引擎),并根據(jù)返回結(jié)果顯示不同的頁(yè)面。這一例子中,我們使用了一個(gè)Struts行為,但其代碼是和使用其它表現(xiàn)層框架甚至一個(gè)Servlet或一個(gè)Jsp頁(yè)面是很類似的。這個(gè)片斷使用了struts-config.xml配置文件,JSP頁(yè)面來(lái)上傳/顯示數(shù)據(jù),并且生成WAR文件來(lái)進(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)建新對(duì)象 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ù)相對(duì)應(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)向合適的頁(yè)面 if ('YES'.equals( testOffer.getRecommendPurchase()){ return mapping.findForward('YES_WEB_PAGE'); } //otherwise default to the no page//否則指向無(wú)此頁(yè)面 return mapping.findForward('NO_WEB_PAGE'); }}這個(gè)例子包含了幾個(gè)東西。經(jīng)常,我們需要的數(shù)據(jù)是用戶通過(guò)好幾個(gè)網(wǎng)頁(yè)傳來(lái)的,因此在這一例子中展示了通過(guò)session中的StockOffer對(duì)象來(lái)保存過(guò)去以來(lái)的數(shù)據(jù)。下一步,如果用戶改變了一些值,我們更新StockOffer對(duì)象。然后我們重置了rcommendPurchase標(biāo)志用以在調(diào)用商業(yè)邏輯層之前清除以前的結(jié)果。最后我們使用商業(yè)邏輯層的返回來(lái)決定讓用戶轉(zhuǎn)向哪一頁(yè)面。在這一例子中,需要注意我們將商業(yè)邏輯(買或不買一支股票)與表現(xiàn)層邏輯(決定轉(zhuǎn)向哪一頁(yè)面)分離開來(lái)。這將使我們可以在不同的應(yīng)用中重用我們的商業(yè)規(guī)則。另外,看一下狀態(tài)信息(用戶已經(jīng)告知我們的東西)是存儲(chǔ)在Session中的StockOffer對(duì)象中的,并沒(méi)有在商業(yè)層中。這樣就保證了商業(yè)層的無(wú)狀態(tài)性,這將使整個(gè)應(yīng)用更具擴(kuò)展性和性能。集成規(guī)則引擎與數(shù)據(jù)庫(kù)層到目前為止,我們的應(yīng)用已經(jīng)有一個(gè)web表現(xiàn)層和一個(gè)商業(yè)層的規(guī)則引擎,但還沒(méi)有方法與數(shù)據(jù)庫(kù)進(jìn)行交互。這一節(jié)的例子將展示如何實(shí)現(xiàn)。我們的例子是基于數(shù)據(jù)訪問(wèn)對(duì)象(DAO)模式的,它把所有與數(shù)據(jù)庫(kù)(或后端數(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)通過(guò)商業(yè)層。這將使我們的代碼更容易組織和閱讀。● 盡可能地,我們應(yīng)讓我們的數(shù)據(jù)層無(wú)狀態(tài)-我們應(yīng)該在其它的地方存放客戶端數(shù)據(jù)(比如:web前端的session,就像前面的例子)。這不同于我們可以在這一層做的數(shù)據(jù)緩存。兩者的區(qū)別在于狀態(tài)信息經(jīng)常是用戶定義的,而我們?cè)跀?shù)據(jù)層緩存的數(shù)據(jù)應(yīng)該是整個(gè)應(yīng)用共享的。這樣的層次提升了性能。● 我們應(yīng)該讓商業(yè)邏輯決定數(shù)據(jù)是否需要――如不需要,提取數(shù)據(jù)的調(diào)用就不應(yīng)該執(zhí)行。為了實(shí)現(xiàn)我們簡(jiǎn)單的數(shù)據(jù)訪問(wèn)對(duì)象,我們創(chuàng)建三個(gè)新對(duì)象:StockNameDao, DaoImplementation,和 DaoFactoryStockNameDao是一個(gè)定義了兩個(gè)方法的接口:getStockName()返回一個(gè)我們可以處理的股票名稱的列表,isOnStockList()檢查一個(gè)給定的股票是否在處理列表中。我們的商業(yè)層在需要這些信息時(shí)會(huì)調(diào)用這些方法。DaoImplementation是StockNameDao的一個(gè)實(shí)現(xiàn)。這里的數(shù)據(jù)是硬編碼的,但我們可以通過(guò)查詢數(shù)據(jù)庫(kù)或通過(guò)像Bloomberg這樣的web service提取信息。DaoFactory我們用來(lái)生成合適的StockNameDao實(shí)例。不直接創(chuàng)建對(duì)象而使用這一小驟的好處在于,它充許我們?cè)谶\(yùn)行時(shí)刻決定使用哪一個(gè)DAO實(shí)現(xiàn)(這是像Spring這樣的框架特別擅長(zhǎng)的).一個(gè)factory(工廠)可以返回多種類型的DAO(比如:StockNameDao, StockPriceDao, StockHistoryDao),這意味著我們可以通過(guò)我們的DaoFactory,讓規(guī)則自己決定需要什么數(shù)據(jù)和DAO.這是StockNameDao接口:/** * Defines a Data Access Object - a non data * source specific way of obtaining data. * 定義一個(gè)數(shù)據(jù)存取對(duì)象-一種非數(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ù)存取對(duì)象的具體定義 */ 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è)硬編碼的例子,一般來(lái) * 說(shuō)我們應(yīng)該從數(shù)據(jù)庫(kù)或其它數(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
標(biāo)簽:
Java
相關(guān)文章:
1. 基于Struts技術(shù)的Web應(yīng)用設(shè)計(jì)與實(shí)現(xiàn)_Java開源項(xiàng)目_Struts2. 將properties文件的配置設(shè)置為整個(gè)Web應(yīng)用的全局變量實(shí)現(xiàn)方法3. PHP 實(shí)現(xiàn) WebSocket 協(xié)議原理與應(yīng)用詳解4. 構(gòu)建Vue3桌面應(yīng)用程序的方法5. PHP輸出控制功能在簡(jiǎn)繁體轉(zhuǎn)換中的應(yīng)用 6. IDEA導(dǎo)出jar打包成exe應(yīng)用程序的小結(jié)7. 為你的應(yīng)用程序添加動(dòng)態(tài)Java代碼8. javascript設(shè)計(jì)模式 ? 抽象工廠模式原理與應(yīng)用實(shí)例分析9. asp.net core應(yīng)用docke部署到centos7的全過(guò)程10. Android啟動(dòng)頁(yè)優(yōu)化之實(shí)現(xiàn)應(yīng)用秒開
排行榜
