欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
為你的基于SPRING的應用增加簡(jiǎn)單規則引擎
摘要

這篇文章解釋了在J2EE應用中規則引擎及聲明性業(yè)務(wù)邏輯的優(yōu)點(diǎn),并且描述如何為流行的Spring框架開(kāi)發(fā)簡(jiǎn)單的規則引擎。此文需要讀者對Spring有基本的了解。

任何大一點(diǎn)的軟件項目都包含了許多叫做業(yè)務(wù)邏輯的東西。業(yè)務(wù)邏輯的準確描述還是有爭議的。在為典型應用軟件的生成的大量代碼中,到處都是為如訂單處理、武器控制系統、圖形繪制等功能工作的零碎代碼。這些代碼與其他如處理持久化、日志、事務(wù)、語(yǔ)言偏好、框架特性及其他現代企業(yè)級應用有明顯不同。

業(yè)務(wù)邏輯通常與其他代碼塊緊密的混和在一起。當重量級的侵入式框架(如EJB)被使用時(shí),區別業(yè)務(wù)邏輯與框架生成的代碼就變得非常困難。

有一個(gè)軟件需求在需求定義文檔很難準確描述,卻擁有使軟件項目成功或失敗的能力:適應性,這是用來(lái)衡量軟件響應業(yè)務(wù)變更容易程度的標準。

現代企業(yè)要求響應快速及靈活,他們對企業(yè)軟件也有同樣的要求??赡苣憬裉煨量鄬?shí)現的業(yè)務(wù)規則在明天就被廢棄了而且要求你根據變更快速而準確的改變。當你的包含業(yè)務(wù)邏輯的代碼隱藏在大量其他代碼中時(shí),修改就變得緩慢、痛若且易出錯了。

在今天的企業(yè)級軟件中沒(méi)有奇跡,比較流行的是規則引擎和各種業(yè)務(wù)過(guò)程管理(BPM)系統。如果你看一下市場(chǎng)上的宣傳,這類(lèi)工具都承諾一件事:保存在倉庫中的捕獲業(yè)務(wù)邏輯的圣杯能夠清晰的分離且由自己維護,并隨時(shí)準備讓你現有的應用來(lái)調用。

雖然商業(yè)的規則引擎和BPM系統有許多優(yōu)點(diǎn),但也有不少缺點(diǎn)。最大的缺點(diǎn)就是價(jià)格,通常很容易就達到7位數。另一個(gè)就是除了主要的行業(yè)規范和眾多記在紙上的標準外缺乏事實(shí)上的標準。而且隨著(zhù)越來(lái)越多的軟件項目采用敏捷、輕量級的快速開(kāi)發(fā)方法,這些重量級的工具變得不符合潮流了。
在這篇文章中,我們建立了一個(gè)簡(jiǎn)單的規則引擎,一方面平衡系統與業(yè)務(wù)邏輯的分離,另一方面由于他基于目前流行的強大的J2EE框架因而不需要承受商業(yè)軟件的復雜性與不協(xié)調性。

J2EE世界中的Spring時(shí)代

在企業(yè)級軟件的復雜性變得不能忍受及業(yè)務(wù)邏輯問(wèn)題越來(lái)越重要時(shí),Spring及類(lèi)似的框架產(chǎn)生了??梢詳喽⊿pring在以后很長(cháng)一段時(shí)間內是企業(yè)級Java中的佼佼者。Spring提供了很多工具及少量代碼約定使J2EE的開(kāi)發(fā)更面向對象,更容易也更有趣。

Spring的核心是IoC原則,這是一個(gè)奇特而超負荷的名字,但包含下面的簡(jiǎn)單想法:
●功能代碼需要分開(kāi)到更小的可管理片斷
●這些片斷是簡(jiǎn)單的,標準的JavaBean(簡(jiǎn)單的Java類(lèi)擁有但不包含全部的JavaBean規范)
●你不需要參與管理這些Bean(如創(chuàng )建、銷(xiāo)毀、設置依賴(lài))
●相反Spring容器通過(guò)上下文定義來(lái)為你做這些(通常為XML文件格式)

Spring也提供了很多其他特性,如完整而強大的MVC框架,簡(jiǎn)便的JDBC開(kāi)發(fā)包裝及其他框架。但那些主題已經(jīng)超出這篇幅文章的討論范圍。

在我描述需要什么來(lái)創(chuàng )建基于SPRING應用的簡(jiǎn)單規則引擎之前,讓我們想一下為什么這是一種好的想法。

規則引擎設計有兩點(diǎn)有趣的特性使其更有價(jià)值:
●首先,從應用領(lǐng)域分離了業(yè)務(wù)邏輯代碼。
●其次,可配置性意味著(zhù)業(yè)務(wù)規則的定義及其使用的順序被存儲在應用的外部,這樣就可以由規則創(chuàng )建人員來(lái)控制而不是應用的使用者或者開(kāi)發(fā)人員了。

Spring為規則引擎提供了一個(gè)好的方法。一個(gè)良好編碼的Spring應用的強組件化的設計會(huì )使你的代碼變成更小的、可管理的分散片斷,這樣就更易在Spring的上下文定義中配置。
繼續了解在規則引擎設計的需求與Spring設計提供的功能之間的結合點(diǎn)。

基于Spring的規則引擎的設計

我們在Spring控制的JavaBean基礎上開(kāi)始設計,這里我們叫做規則引擎組件。我們來(lái)定義下面兩種我們可能需要的組件類(lèi)型:
●操作—在應用邏輯中確定用來(lái)做什么的組件
●規則—在一系列行為的邏輯流中做出決定的組件

我們都是面向對象設計的追隨者,下面的基類(lèi)建立了所有我們的組件需要通過(guò)參數被其他組件調用的基本功能:

public abstract class AbstractComponent {
   public abstract void execute(Object arg) throws Exception;
}


當然基類(lèi)是抽象的因為我們根本不需要這樣的實(shí)例。
AbstractAction的代碼擴展了基類(lèi)來(lái)實(shí)現其他具體的操作:

public abstract class AbstractAction extends AbstractComponent {

   private AbstractComponent nextStep;
  
   public void execute(Object arg) throws Exception {
      this.doExecute(arg);
      if(nextStep != null)
         nextStep.execute(arg);
   }
  
   protected abstract void doExecute(Object arg) throws Exception;

   public void setNextStep(AbstractComponent nextStep) {
      this.nextStep = nextStep;
   }

   public AbstractComponent getNextStep() {
      return nextStep;
   }

}


你可以看到,AbstractAction做兩件事:首先他保存在規則引擎中被激活的下一個(gè)組件的定義;其次在他的execute()方法中,調用被具體類(lèi)實(shí)現的doExecute()方法,在doExecute()返回后,如果存在下一個(gè)組件則調用他。
我們的AbstractRule也相當簡(jiǎn)單:

public abstract class AbstractRule extends AbstractComponent {

   private AbstractComponent positiveOutcomeStep;
   private AbstractComponent negativeOutcomeStep;
  
   public void execute(Object arg) throws Exception {
      boolean outcome = makeDecision(arg);
      if(outcome)
         positiveOutcomeStep.execute(arg);
      else
         negativeOutcomeStep.execute(arg);

   }

   protected abstract boolean makeDecision(Object arg) throws Exception;


// 為簡(jiǎn)單起見(jiàn),positiveOutcomeStep和negativeOutcomeStep 的Getters 和 setters均已省略
在其execute()方法中,AbstractAction調用由子類(lèi)實(shí)現的makeDecision()方法,然后根據方法的返回值,調用組件定義的肯定或否定結果的方法。
在我們介紹了SpringRuleEngine類(lèi)后我們的設計就基本完成了:

public class SpringRuleEngine {
  
   private AbstractComponent firstStep;
  
   public void setFirstStep(AbstractComponent firstStep) {
      this.firstStep = firstStep;
   }
  
   public void processRequest(Object arg) throws Exception {
      firstStep.execute(arg);
   }
  
}


這就是我們規則引擎主類(lèi)的全部:定義第一個(gè)業(yè)務(wù)邏輯中的組件及開(kāi)始執行的方法。
但是請稍等,在哪里綁定我們的類(lèi)使之可以工作呢?下面你就可以看到如何利用Spring來(lái)幫助我們完成工作的方法了。

在操作中的基于Spring的規則引擎

讓我們看一下這個(gè)框架如何工作的具體實(shí)例吧。想象下面的用例:我們需要開(kāi)發(fā)負責貸款申請的應用程序。我們需要滿(mǎn)足下面的條件:
●檢查應用的完整性否則駁回
●檢查應用是否來(lái)自我們授權處理業(yè)務(wù)的應用。
●檢查申請者的月收支比是否滿(mǎn)足我們的要求。
●輸入的申請通過(guò)我們不知道實(shí)現細節的持久服務(wù)被存儲在數據庫中,我們只知道他的接口(可能這個(gè)開(kāi)發(fā)被外包到印度了)
●業(yè)務(wù)規則是可以改變的,這也是為什么需要規則引擎的設計了。

首先,設計一個(gè)表示貸款申請的類(lèi):

public class LoanApplication {
  
   public static final String INVALID_STATE = "Sorry we are not doing business in your state";
   public static final String INVALID_INCOME_EXPENSE_RATIO = "Sorry we cannot provide the loan given this expense/income ratio";
   public static final String APPROVED = "Your application has been approved";
   public static final String INSUFFICIENT_DATA = "You did not provide enough information on your application";
   public static final String INPROGRESS = "in progress";
  
   public static final String[] STATUSES =
      new String[] {
         INSUFFICIENT_DATA, INVALID_INCOME_EXPENSE_RATIO, INVALID_STATE, APPROVED, INPROGRESS
      };

   private String firstName;
   private String lastName;
   private double income;
   private double expences;
   private String stateCode;
   private String status;
  
   public void setStatus(String status) {
      if(!Arrays.asList(STATUSES).contains(status))
         throw new IllegalArgumentException("invalid status:" + status);
      this.status = status;
   }

// 其他getters and setters已被省略

}


我們使用的持久服務(wù)擁有如下接口:

public interface LoanApplicationPersistenceInterface {
   public void recordApproval(LoanApplication application) throws Exception;
   public void recordRejection(LoanApplication application) throws Exception;
   public void recordIncomplete(LoanApplication application) throws Exception;
}


我們迅速開(kāi)發(fā)一個(gè)什么也不做只是用來(lái)滿(mǎn)足接口約定的MockLoanApplicationPersistence類(lèi)來(lái)欺騙接口。
我們使用下面的SpringRuleEngine類(lèi)的子類(lèi)來(lái)加載Spring上下文并開(kāi)始處理:

public class LoanProcessRuleEngine extends SpringRuleEngine {
   public static final SpringRuleEngine getEngine(String name) {
      ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("SpringRuleEngineContext.xml");
      return (SpringRuleEngine) context.getBean(name);
   }
}


這時(shí)候,我們已經(jīng)有了代碼框架了,因此是時(shí)候寫(xiě)JUnit測試了,代碼如下。其中包含一些假設:我們期望公司僅在兩種州運作,德克薩斯和密歇根。而且我們只接受收支比在70%或更好的人的貸款申請。

public class SpringRuleEngineTest extends TestCase {

   public void testSuccessfulFlow() throws Exception {
      SpringRuleEngine engine = LoanProcessRuleEngine.getEngine("SharkysExpressLoansApplicationProcessor");
      LoanApplication application = new LoanApplication();
      application.setFirstName("John");
      application.setLastName("Doe");
      application.setStateCode("TX");
      application.setExpences(4500);
      application.setIncome(7000);
      engine.processRequest(application);
      assertEquals(LoanApplication.APPROVED, application.getStatus());
   }
  
   public void testInvalidState() throws Exception {
      SpringRuleEngine engine = LoanProcessRuleEngine.getEngine("SharkysExpressLoansApplicationProcessor");
      LoanApplication application = new LoanApplication();
      application.setFirstName("John");
      application.setLastName("Doe");
      application.setStateCode("OK");
      application.setExpences(4500);
      application.setIncome(7000);
      engine.processRequest(application);
      assertEquals(LoanApplication.INVALID_STATE, application.getStatus());
   }
  
   public void testInvalidRatio() throws Exception {
      SpringRuleEngine engine = LoanProcessRuleEngine.getEngine("SharkysExpressLoansApplicationProcessor");
      LoanApplication application = new LoanApplication();
      application.setFirstName("John");
      application.setLastName("Doe");
      application.setStateCode("MI");
      application.setIncome(7000);
      application.setExpences(0.80 * 7000); //too high      
      engine.processRequest(application);
      assertEquals(LoanApplication.INVALID_INCOME_EXPENSE_RATIO, application.getStatus());
   }
  
   public void testIncompleteApplication() throws Exception {      
      SpringRuleEngine engine = LoanProcessRuleEngine.getEngine("SharkysExpressLoansApplicationProcessor");
      LoanApplication application = new LoanApplication();
      engine.processRequest(application);
      assertEquals(LoanApplication.INSUFFICIENT_DATA, application.getStatus());
   }

      
顯然單元測試會(huì )失敗因為我們還沒(méi)有實(shí)現任何的邏輯。然而,隨著(zhù)項目的進(jìn)展,越來(lái)越多的測試通過(guò),最后JUnit測試就全部通過(guò)了。
讓我們繼續操作和規則的實(shí)現。我們希望操作與持久服務(wù)交互因此我們需要一個(gè)通用基類(lèi):

public abstract class AbstractPersistenceAwareAction extends AbstractAction {
   private LoanApplicationPersistenceInterface persistenceService;
   public void setPersistenceService(LoanApplicationPersistenceInterface persistenceService) {
      this.persistenceService = persistenceService;
   }
   public LoanApplicationPersistenceInterface getPersistenceService() {
      return persistenceService;
   }
}


在我們的進(jìn)程中第一個(gè)請求貸款申請的業(yè)務(wù)規則已經(jīng)完成:

public class ValidApplicationRule extends AbstractRule {
   protected boolean makeDecision(Object arg) throws Exception {
      LoanApplication application = (LoanApplication) arg;
      if(application.getExpences() == 0 ||
            application.getFirstName() == null ||
            application.getIncome() == 0 ||
            application.getLastName() == null ||
            application.getStateCode() == null) {
         application.setStatus(LoanApplication.INSUFFICIENT_DATA);
         return false;
      }
      return true;
   }
}


注意這個(gè)類(lèi)的一些有趣的現象:他是完全自包含的。他可以由自己實(shí)例化或者任何外部的應用容器,而類(lèi)中的邏輯可以獨立的開(kāi)發(fā)和測試。這些現象使類(lèi)成為基于規則應用的完美的程序塊。

現在是時(shí)候通過(guò)Spring容器來(lái)綁定對象了。就象你在單元測試中看到的一樣,我們使用LoanProcessRuleEngine類(lèi)作為入口指向請求名為SharkysExpressLoansApplicationProcessor的Bean的規則引擎。下面是這個(gè)Bean如何在SpringRuleEngineContext.xml定義:

   <!-- 規則引擎處理器 -->
   <bean id="SharkysExpressLoansApplicationProcessor" class="SpringRuleEngine">
      <property name="firstStep">
         <ref bean="ValidApplicationRule"/>
      </property>
   </bean>
這個(gè)Bean簡(jiǎn)單地指明ValidApplicationRule為業(yè)務(wù)處理的第一個(gè)步驟。這個(gè)組件如下定義:
   <!-- validation -->
   <bean id="ValidApplicationRule" class="ValidApplicationRule">
      <property name="positiveOutcomeStep">
         <ref bean="ValidStateRule"/>
      </property>
      <property name="negativeOutcomeStep">
         <ref bean="RejectionAction"></ref>
      </property>
   </bean>


你可以看到,規則自身也在Spring上下文中定義:如果貸款申請是合法的,應用會(huì )檢查是否正確的州;否則控制傳遞給RejectionAction。
RejectionAction也很簡(jiǎn)單:

public class ProcessRejectionAction extends AbstractPersistenceAwareAction {
   protected void doExecute(Object arg) throws Exception {
      LoanApplication application = (LoanApplication) arg;
      if(LoanApplication.INSUFFICIENT_DATA.equals(application.getStatus()))
         this.getPersistenceService().recordIncomplete(application);
      else
         this.getPersistenceService().recordRejection(application);
   }
}


它在Spring上下文中如下定義(注意引用了被偽類(lèi)欺騙的持久服務(wù)):

   <!-- rejection -->
   <bean id="RejectionAction" class="ProcessRejectionAction">
      <property name="persistenceService">
         <ref bean="LoanApplicationPersistenceService"/>
      </property>

   </bean>
   <!-- persistence service -->
   <bean id="LoanApplicationPersistenceService" class="MockLoanApplicationPersistence"/>


我們的下一個(gè)業(yè)務(wù)規則檢查是否貸款申請來(lái)自合法的州:

public class ValidStateRule extends AbstractRule {

   private List validStates;
  
   protected boolean makeDecision(Object arg) throws Exception {
      LoanApplication application = (LoanApplication) arg;
      if(validStates.contains(application.getStateCode())) {
         return true;
      }
      application.setStatus(LoanApplication.INVALID_STATE);
      return false;
   }

   public void setValidStates(List validStates) {
      this.validStates = validStates;
   }
}


有趣的是,我們的代碼并不知道哪些州是合法的。這些業(yè)務(wù)信息由上下文來(lái)定義:

   <!-- check valid state -->
   <bean id="ValidStateRule" class="ValidStateRule">
      <property name="validStates">
         <list>
            <value>TX</value>
            <value>MI</value>
         </list>
      </property>
      <property name="positiveOutcomeStep">
         <ref bean="ValidIncomeExpenseRatioRule"/>
      </property>
      <property name="negativeOutcomeStep">
         <ref bean="RejectionAction"></ref>
      </property>
   </bean>


Spring的內建功能再一次讓我們從代碼中抽取出邏輯流程和參數數據,僅在外部配置就可以了。
如你所見(jiàn),Spring應用容器為我們的類(lèi)提供了所有必須的綁定。在啟動(dòng)時(shí),Spring創(chuàng )建所有必須的對象并設置相關(guān)的依賴(lài)。在運行時(shí),我們的業(yè)務(wù)規則通過(guò)定義在Spring上下文而不是代碼中的邏輯和參數數據來(lái)執行。

貸款申請示例的其他部分可以用相同方法來(lái)配置和開(kāi)發(fā)。完整的源程序及對應的Spring配置可以在資源中找到。

總結

在這篇文章中,我演示了通過(guò)Spring幫助你開(kāi)發(fā)基于規則應用的眾多方法中的一部分。你也可以使用其內置的AOP來(lái)支持在你的規則和操作中混合日志及事務(wù)代碼而不會(huì )污染你先前的業(yè)務(wù)邏輯。

SPRING應用上下文是可以重新加載的。應用可以修改業(yè)務(wù)規則和參數(通過(guò)修改XML文件)并在運行中重新加載上下文。想象這么做的GUI應用。這么做可以提供與價(jià)格為數百萬(wàn)的商業(yè)的規則引擎系統的類(lèi)似功能。
很期望這篇文章可以幫助你嘗試一些新鮮而以令人振奮的方法來(lái)使你的代碼在將來(lái)更加有效。

關(guān)于作者
Mikhail Garber是居住在達拉斯的獨立技術(shù)顧問(wèn),擁有超過(guò)12年的企業(yè)級軟件開(kāi)發(fā)的經(jīng)驗。尤其擅長(cháng)Java/J2EE、數據庫、消息和開(kāi)源方案。已經(jīng)有很多如Mary Kay Cosmetics, Boeing Defense and Space, Verizon Wireless, the US government, Lockheed Martin及其他的組織接受他的指導。

資源
●下載這篇文章對應的源程序
http://www.javaworld.com/javaworld/jw-04-2005/ruleengine/jw-0425-ruleengine.zip
●Spring:
http://www.Springframework.org
●更多有關(guān)SPRING的文章,瀏覽最近的JavaWorld的這些文章:
●“使用SPRING創(chuàng )建簡(jiǎn)單的工作流引擎” , Steve Dodge (2005年4月):
http://www.javaworld.com/javaworld/jw-04-2005/jw-0411-Spring.html
●"Pro Spring: Spring and EJB," Rob Harrop及Jan Machacek (2005年2月):
http://www.javaworld.com/javaworld/jw-02-2005/jw-0214-Springejb.html
●“讓你的ANT享受Spring” ,Josef Betancourt (2005年2月):
http://www.javaworld.com/javaworld/jw-02-2005/jw-0214-antSpring.html
●利用Spring, Struts, Hibernate, and Axis來(lái)“設計簡(jiǎn)單的面向服務(wù)的J2EE應用框架”,Fangjian Wu (2004年10月):
http://www.javaworld.com/javaworld/jw-10-2004/jw-1004-soa.html
●通過(guò)“用JSF工作”學(xué)習如何運用JavaServer Faces, Spring, and Hibernate構建網(wǎng)絡(luò )應用, Derek Yang Shen (2004年7月):
http://www.javaworld.com/javaworld/jw-07-2004/jw-0719-jsf.html
●Mikhail Garber: “為對象持久使用搜索引擎技術(shù)”,(JavaWorld, 2005年1月):
http://www.javaworld.com/javaworld/jw-01-2005/jw-0103-search.html
●更多有關(guān)J2EE應用開(kāi)發(fā)的文章,可以瀏覽JavaWorld的主題索引的J2EE部分
http://www.javaworld.com/channel_content/jw-j2ee-index.shtml?
●更多JAVA開(kāi)發(fā)工具的文章,可以游覽JavaWorld的主題索引的開(kāi)發(fā)工具部分
http://www.javaworld.com/channel_content/jw-tools-index.shtml
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
spring-boot(七)servlet等容器對象配置
Spring - OpenSource Project - JavaWorld@TW
依賴(lài)注入三種方式
Spring Security(3.1.7) CAS Authentication
Spring 中的國際化Message的簡(jiǎn)單例子(ApplicationContext)
Spring Boot 引入自定義yml
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久