亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

使用struts+spring+hibernate 組裝web應(yīng)用

系統(tǒng) 2578 0

摘要:

這篇文章將討論怎樣組合幾個著名的框架去做到松耦合的目的,怎樣建立你的構(gòu)架,怎樣讓你的各個應(yīng)用層保持一致。富于挑戰(zhàn)的是:組合這些框架使得每一層都以一種松耦合的方式彼此溝通,而與底層的技術(shù)無關(guān)。這篇文章將使用3種流行的開源框架來討論組合框架的策略

其實,就算用Java建造一個不是很煩瑣的web應(yīng)用程序,也不是件輕松的事情。當(dāng)為一個應(yīng)用程序建造一個構(gòu)架時有許多事情需要考慮。從高層來說,開發(fā)者需要考慮:怎樣建立用戶接口?在哪里處理業(yè)務(wù)邏輯?和怎樣持久化應(yīng)用數(shù)據(jù)。這三層每一層都有它們各自的問題需要回答。 各個層次應(yīng)該使用什么技術(shù)?怎樣才能把應(yīng)用程序設(shè)計得松耦合和能靈活改變?構(gòu)架允許層的替換不會影響到其它層嗎?應(yīng)用程序怎樣處理容器級的服務(wù),比如事務(wù)處理?

  當(dāng)為你的web應(yīng)用程序創(chuàng)建一個構(gòu)架時,需要涉及到相當(dāng)多的問題。幸運的是,已經(jīng)有不少開發(fā)者已經(jīng)遇到過這類重復(fù)發(fā)生的問題,并且建立了處理這類問題的框架。一個好框架具備以下幾點: 減輕開發(fā)者處理復(fù)雜的問題的負擔(dān)(“不重復(fù)發(fā)明輪子”);內(nèi)部定義為可擴展的;有一個強大的用戶群支持??蚣芡ǔD軌蚝芎玫慕鉀Q一方面的問題。然而,你的應(yīng)用程序有幾個層可能都需要它們各自的框架。就如解決你的用戶接口(UI)問題時你就不應(yīng)該把事務(wù)邏輯和持久化邏輯摻雜進來。例如,你不應(yīng)該在控制器里面寫jdbc代碼,使它包含有業(yè)務(wù)邏輯,這不是控制器應(yīng)該提供的功能。它應(yīng)該是輕量級的,代理來自用戶接口(UI)外的調(diào)用請求給其它服務(wù)于這些請求的應(yīng)用層。好的框架自然的形成代碼如何分布的指導(dǎo)。更重要的是,框架減輕開發(fā)者從頭開始寫像持久層這樣的代碼的痛苦,使他們專注于對客戶來說很重要的應(yīng)用邏輯。

  這篇文章將討論怎樣組合幾個著名的框架去做到松耦合的目的,怎樣建立你的構(gòu)架,怎樣讓你的各個應(yīng)用層保持一致。富于挑戰(zhàn)的是:組合這些框架使得每一層都以一種松耦合的方式彼此溝通,而與底層的技術(shù)無關(guān)。這篇文章將使用3種流行的開源框架來討論組合框架的策略。表現(xiàn)層我們將使用Struts;業(yè)務(wù)層我們將使用Spring;持久層使用Hibrenate.你也可以在你的應(yīng)用程序中替換這些框架中的任何一種而得到同樣的效果。圖1展示了當(dāng)這些框架組合在一起時從高層看是什么樣子。

圖1用Struts, Spring, 和 Hibernate框架構(gòu)建的概覽

應(yīng)用程序的分層

  大多數(shù)不復(fù)雜的web應(yīng)用都能被分成至少4個各負其責(zé)的層次。這些層次是:表現(xiàn)層、持久層、業(yè)務(wù)層、領(lǐng)域模型層。每層在應(yīng)用程序中都有明確的責(zé)任,不應(yīng)該和其它層混淆功能。每一應(yīng)用層應(yīng)該彼此獨立但要給他們之間放一個通訊接口。讓我們從審視各個層開始,討論這些層應(yīng)該提供什么和不應(yīng)該提供什么。

表現(xiàn)層

在一個典型的web應(yīng)用的一端是表現(xiàn)層。很多Java開發(fā)者也理解Struts所提供的。然而,太常見的是,他們把像業(yè)務(wù)邏輯之類的耦合的代碼放進了一個org.apache.struts.Action。所以,讓我們在像Struts這樣一個框架應(yīng)該提供什么上取得一致意見。這兒是Struts負責(zé)的:

為用戶管理請求和響應(yīng);
  提供一個控制器代理調(diào)用業(yè)務(wù)邏輯和其它上層處理;
  處理從其它層擲出給一個Struts Action的異常;
  為顯示提供一個模型;
  執(zhí)行用戶接口驗證。

  這兒是一些經(jīng)常用Struts編寫的但是卻不應(yīng)該和Struts表現(xiàn)層相伴的項目:
  直接和數(shù)據(jù)庫通訊,比如JDBC調(diào)用;
  業(yè)務(wù)邏輯和與你的應(yīng)用程序相關(guān)的驗證;
  事務(wù)管理;
  在表現(xiàn)層中引入這種代碼將導(dǎo)致典型耦合和討厭的維護。

持久層

在典型web應(yīng)用的另一端是持久層。這通常是使事情迅速失控的地方。開發(fā)者低估了構(gòu)建他們自己的持久層框架的挑戰(zhàn)性。一般來說,機構(gòu)內(nèi)部自己寫的持久層不僅需要大量的開發(fā)時間,而且還經(jīng)常缺少功能和變得難以控制。有幾個開源的“對象-關(guān)系映射”框架非常解決問題。尤其是,Hibernate框架為java提供了"對象-關(guān)系持久化"機制和查詢服務(wù)。Hibernate對那些已經(jīng)熟悉了SQL和JDBC API的Java開發(fā)者有一個適中的學(xué)習(xí)曲線。Hibernate持久對象是基于簡單舊式Java對象和Java集合。此外,使用Hibernate并不妨礙你正在使用的IDE。下面的列表包含了你該寫在一個持久層框架里的代碼類型:

  查詢相關(guān)的信息成為對象。Hibernate通過一種叫作HQL的面向?qū)ο蟮牟樵冋Z言或者使用條件表達式API來做這個事情。 HQL非常類似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。有一些新的專用的HQL語言成分要學(xué);不過,它們?nèi)菀桌斫舛椅臋n做得好。HQL是一種使用來查詢對象的自然語言,花很小的代價就能學(xué)習(xí)它。

  保存、更新、刪除儲存在數(shù)據(jù)庫中的信息。

像Hibernate這樣的高級“對象-關(guān)系”映射框架提供對大多數(shù)主流SQL數(shù)據(jù)庫的支持,它們支持“父/子”關(guān)系、事務(wù)處理、繼承和多態(tài)。

  這兒是一些應(yīng)該在持久層里被避免的項目:

  業(yè)務(wù)邏輯應(yīng)該在你的應(yīng)用的一個高一些的層次里。持久層里僅僅允許數(shù)據(jù)存取操作。

  你不應(yīng)該把持久層邏輯和你的表現(xiàn)層邏輯攪在一起。避免像JSPs或基于servlet的類這些表現(xiàn)層組件里的邏輯和數(shù)據(jù)存取直接通訊。通過把持久層邏輯隔離進它自己的層,應(yīng)用程序變得易于修改而不會影響在其它層的代碼。例如:Hebernate能夠被其它持久層框架或者API代替而不會修改在其它任何層的代碼。

業(yè)務(wù)層

  在一個典型的web應(yīng)用程序的中間的組件是業(yè)務(wù)層或服務(wù)層。從編碼的視角來看,這個服務(wù)層是最容易被忽視的一層。不難在用戶接口層或者持久層里找到散布在其中的這種類型的代碼。這不是正確的地方,因為這導(dǎo)致了應(yīng)用程序的緊耦合,這樣一來,隨著時間推移代碼將很難維護。幸好,針對這一問題有好幾種Frameworks存在。在這個領(lǐng)域兩個最流行的框架是Spring和PicoContainer,它們叫作微容器,你可以不費力不費神的把你的對象連在一起。所有這些框架都工作在一個簡單的叫作“依賴注入”(也通稱“控制反轉(zhuǎn)”)的概念上。這篇文章將著眼于Spring的為指定的配置參數(shù)通過bean屬性的setter注入的使用。Spring也提供了一個構(gòu)建器注入的復(fù)雜形式作為setter注入的一個替代。對象們被一個簡單的XML文件連在一起,這個XML文件含有到像事務(wù)管理器、對象工廠、包含業(yè)務(wù)邏輯的服務(wù)對象、和數(shù)據(jù)存取對象這些對象的引用。

  這篇文章的后面將用例子來把Spring使用這些概念的方法說得更清楚一些。業(yè)務(wù)層應(yīng)該負責(zé)下面這些事情:

處理應(yīng)用程序的業(yè)務(wù)邏輯和業(yè)務(wù)驗證;
  管理事務(wù);
  預(yù)留和其它層交互的接口;
  管理業(yè)務(wù)層對象之間的依賴;
  增加在表現(xiàn)層和持久層之間的靈活性,使它們互不直接通訊;
  從表現(xiàn)層中提供一個上下文給業(yè)務(wù)層獲得業(yè)務(wù)服務(wù);
  管理從業(yè)務(wù)邏輯到持久層的實現(xiàn)。

領(lǐng)域模型層

最后,因為我們討論的是一個不是很復(fù)雜的、基于web的應(yīng)用程序,我們需要一組能在不同的層之間移動的對象。領(lǐng)域?qū)ο髮佑赡切┐憩F(xiàn)實世界中的業(yè)務(wù)對象的對象們組成,比如:一份訂單、訂單項、產(chǎn)品等等。這個層讓開發(fā)者停止建立和維護不必要的數(shù)據(jù)傳輸對象(或者叫作DTOs),來匹配他們的領(lǐng)域?qū)ο蟆@?,Hibernate允許你把數(shù)據(jù)庫信息讀進領(lǐng)域?qū)ο蟮囊粋€對象圖,這樣你可以在連接斷開的情況下把這些數(shù)據(jù)顯示到UI層。那些對象也能被更新和送回到持久層并在數(shù)據(jù)庫里更新。而且,你不必把對象轉(zhuǎn)化成DTOs,因為DTOs在不同的應(yīng)用層間移動,可能在轉(zhuǎn)換中丟失。這個模型使得Java開發(fā)者自然地以一種面向?qū)ο蟮娘L(fēng)格和對象打交道,沒有附加的編碼。

結(jié)合一個簡單的例子

既然我們已經(jīng)從一個高的層次上理解了這些組件, 現(xiàn)在就讓我們開始實踐吧。在這個例子中,我們還是將合并Struts、Spring、Hibernate框架。每一個這些框架在一篇文章中都有太多的細節(jié)覆蓋到。這篇文章將用一個簡單的例子代碼展示怎樣把它們結(jié)合在一起,而不是進入每個框架的許多細節(jié)。示例應(yīng)用程序?qū)⑹痉兑粋€請求怎樣跨越每一層被服務(wù)的。這個示例應(yīng)用程序的一個用戶能保存一個訂單到數(shù)據(jù)庫中和查看一個在數(shù)據(jù)庫中存在的訂單。進一步的增強可以使用戶更新或刪除一個存在的訂單。

  因為領(lǐng)域?qū)ο髮⒑兔恳粚咏换?,我們將首先?chuàng)建它們。這些對象將使我們定義什么應(yīng)該被持久化,什么業(yè)務(wù)邏輯應(yīng)該被提供,和哪種表現(xiàn)接口應(yīng)該被設(shè)計。然后,我們將配置持久層和用Hibernate為我們的領(lǐng)域?qū)ο蠖x“對象-關(guān)系”映射。然后,我們將定義和配置我們的業(yè)務(wù)對象。在有了這些組件后,我們就能討論用Spring把這些層連在一起。最后,我們將提供一個表現(xiàn)層,它知道怎樣和業(yè)務(wù)服務(wù)層交流和知道怎樣處理從其它層產(chǎn)生的異常。

領(lǐng)域?qū)ο髮?

因為這些對象將和所有層交互,這也許是一個開始編碼的好地方。這個簡單的領(lǐng)域模型將包括一個代表一份訂單的對象和一個代表一個訂單項的對象。訂單對象將和一組訂單項對象有一對多的關(guān)系。例子代碼在領(lǐng)域?qū)佑袃蓚€簡單的對象:

com.meagle.bo.Order.java: 包括一份訂單的概要信息;
  com.meagle.bo.OrderLineItem.java: 包括一份訂單的詳細信息;

考慮一下為你的對象選擇包名,它將反映你的應(yīng)用程序是怎樣分層的。例如:簡單應(yīng)用的領(lǐng)域?qū)ο罂梢苑胚Mcom.meagle.bo包。更多專門的領(lǐng)域?qū)ο髮⒎湃朐赾om.meagle.bo下面的子包里。業(yè)務(wù)邏輯在com.meagle.service包里開始打包,DAO對象放進com.meagle.service.dao.hibernate包。對于forms和actions的表現(xiàn)類分別放入com.meagle.action 和 com.meagle.forms包。準(zhǔn)確的包命名為你的類提供的功能提供一個清楚的區(qū)分,使當(dāng)故障維護時更易于維護,和當(dāng)給應(yīng)用程序增加新的類或包時提供一致性。

持久層配置

用Hibernate設(shè)置持久層涉及到幾個步驟。第一步是進行配置持久化我們的領(lǐng)域業(yè)務(wù)對象。因為我們用于領(lǐng)域?qū)ο蟪志没腍ibernate和POJOs一起工作,因此,訂單和訂單項對象包括的所有的字段的都需要提供getter和setter方法。訂單對象將包括像ID、用戶名、合計、和訂單項這樣一些字段的標(biāo)準(zhǔn)的JavaBean格式的setter和getter方法。訂單項對象將同樣的用JavaBean的格式為它的字段設(shè)置setter和getter方法。

Hibernate在XML文件里映射領(lǐng)域?qū)ο蟮疥P(guān)系數(shù)據(jù)庫。訂單和訂單項對象將有兩個映射文件來表達這種映射。有像XDoclet這樣的工具來幫助這種映射。Hibernate將映射領(lǐng)域?qū)ο蟮竭@些文件:

Order.hbm.xml
  OrderLineItem.hbm.xml

你可以在WebContent/WEB-INF/classes/com/meagle/bo目錄里找到這些生成的文件。配置Hibernate SessionFactory使它知道是在和哪個數(shù)據(jù)庫通信,使用哪個數(shù)據(jù)源或連接池,加載哪些持久對象。SessionFactory提供的Session對象是Java對象和像選取、保存、更新、刪除對象這樣一些持久化功能間的翻譯接口。我們將在后面的部分討論Hibernate操作Session對象需要的SessionFactory配置。

業(yè)務(wù)層配置

既然我們已經(jīng)有了領(lǐng)域?qū)ο螅覀冃枰袠I(yè)務(wù)服務(wù)對象來執(zhí)行應(yīng)用邏輯、執(zhí)行向持久層的調(diào)用、獲得從用戶接口層的請求、處理事務(wù)、處理異常。為了將所有這些連接起來并且易于管理,我們將使用Spring框架的bean管理方面。Spring使用“控制反轉(zhuǎn)”,或者“setter依賴注入”來把這些對象連好,這些對象在一個外部的XML文件中被引用?!翱刂品崔D(zhuǎn)”是一個簡單的概念,它允許對象接受其它的在一個高一些的層次被創(chuàng)建的對象。使用這種方法,你的對象從必須創(chuàng)建其它對象中解放出來并降低對象耦合。

這兒是個不使用IoC的對象創(chuàng)建它的從屬對象的例子,這導(dǎo)致緊的對象耦合:

圖2:沒有使用IoC的對象組織。對象A創(chuàng)建對象B和C。

  這兒是一個使用IoC的例子,它允許對象在一個高一些層次被創(chuàng)建和傳進另外的對象,所以另外的對象能直接使用現(xiàn)成的對象·[譯者注:另外的對象不必再親自創(chuàng)建這些要使用的對象]:


圖3:對象使用IoC組織。對象A包含setter方法,它們接受到對象B和C的接口。這也可以用對象A里的接受對象B和C的構(gòu)建器完成。

建立我們的業(yè)務(wù)服務(wù)對象

我們將在我們的業(yè)務(wù)對象中使用的setter方法接受的是接口,這些接口允許對象的松散定義的實現(xiàn),這些對象將被設(shè)置或者注入。在我們這個例子里我們將使我們的業(yè)務(wù)服務(wù)對象接受一個DAO去控制我們的領(lǐng)域?qū)ο蟮某志没?。?dāng)我們在這篇文章的例子中使用Hibernate,我們可以容易的轉(zhuǎn)換到一個不同的持久框架的實現(xiàn),通知Spring使用新的實現(xiàn)的DAO對象。你能明白編程到接口和使用“依賴注入”模式是怎樣寬松耦合你的業(yè)務(wù)邏輯和你的持久化機制的。

這兒是業(yè)務(wù)服務(wù)對象的接口,它是一個DAO對象依賴的樁。

public interface IOrderService {
 public abstract Order saveNewOrder(Order order)
  throws OrderException,
      OrderMinimumAmountException;
 public abstract List findOrderByUser(
                   String user)
              throws OrderException;
 public abstract Order findOrderById(int id)
              throws OrderException;
 public abstract void setOrderDAO(
               IOrderDAO orderDAO);
}

注意上面的代碼有一個為DAO對象準(zhǔn)備的setter方法。這兒沒有一個getOrderDAO方法因為它不是必要的,因為不太有從外面訪問連著的OrderDAO對象的需要。DAO對象將被用來和我們的持久層溝通。我們將用Spring把業(yè)務(wù)服務(wù)對象和DAO對象連在一起。因為我們編碼到接口,我們不會緊耦合實現(xiàn)。

下一步是寫我們的DAO實現(xiàn)對象。因為Spring有內(nèi)建的對Hibernate的支持,這個例子DAO將繼承HibernateDaoSupport類,這使得我們?nèi)菀兹〉靡粋€到HibernateTemplate類的引用,HibernateTemplate是一個幫助類,它能簡化Hibernate Session的編碼和處理HibernateExceptions。這兒是DAO的接口:

public interface IOrderDAO {
 public abstract Order findOrderById(
                  final int id);
 public abstract List findOrdersPlaceByUser(
              final String placedBy);
 public abstract Order saveOrder(
                final Order order);
}


  我們還有兩個對象要和我們的業(yè)務(wù)層連在一起。這包括HibernateSessionFactory和一個TransactionManager對象。這在Spring配置文件里直接完成。Spring提供一個HibernateTransactionManager,它將從工廠綁定一個Hibernate Session到一個線程來支持事務(wù)。這兒是HibernateSessionFactory和HibernateTransactionManager的Spring配置。

<bean id="mySessionFactory"
    class="org.springframework.orm.hibernate.
       LocalSessionFactoryBean">
 <property name="mappingResources">
  <list>
   <value>
    com/meagle/bo/Order.hbm.xml
   </value>
   <value>
    com/meagle/bo/OrderLineItem.hbm.xml
   </value>
  </list>
 </property>
 <property name="hibernateProperties">
  <props>
   <prop key="hibernate.dialect">
    net.sf.hibernate.dialect.MySQLDialect
   </prop>
   <prop key="hibernate.show_sql">
    false
   </prop>
   <prop key="hibernate.proxool.xml">
    C:/MyWebApps/.../WEB-INF/proxool.xml
   </prop>
   <prop key="hibernate.proxool.pool_alias">
     spring
   </prop>
  </props>
 </property>
</bean>
<!-- Transaction manager for a single Hibernate
SessionFactory (alternative to JTA) -->
<bean id="myTransactionManager"
     class="org.
         springframework.
        orm.
        hibernate.
        HibernateTransactionManager">
 <property name="sessionFactory">
  <ref local="mySessionFactory"/>
 </property>
 </bean>

每一個對象能被Spring配置里的一個<bean>標(biāo)記引用。在這個例子里,bean “mySessionFactory”代表一個HibernateSessionFactory,bean “myTransactionManager”代表一個Hibernate transaction manager。注意transactionManger bean有一個叫作sessionFactory的屬性元素。HibernateTransactionManager有一個為sessionFactory準(zhǔn)備的setter和getter方法,它們是用來當(dāng)Spring容器啟動時的依賴注入。sessionFactory屬性引用mySessionFactory bean。這兩個對象現(xiàn)在當(dāng)Spring容器初始化時將被連在一起。這種連接把你從為引用和創(chuàng)建這些對象而創(chuàng)建singleton對象和工廠中解放出來,這減少了你應(yīng)用程序中的代碼維護。mySessionFactory bean有兩個屬性元素,它們翻譯成為mappingResources 和 hibernatePropertes準(zhǔn)備的setter方法。通常,如果你在Spring之外使用Hibernate,這個配置將被保存在hibernate.cfg.xml文件中。不管怎樣,Spring提供了一個便捷的方式--在Spring配置文件中合并Hibernate的配置。

  既然我們已經(jīng)配置了我們的容器服務(wù)beans和把它們連在了一起,我們需要把我們的業(yè)務(wù)服務(wù)對象和我們的DAO對象連在一起。然后,我們需要把這些對象連接到事務(wù)管理器。

  這是在Spring配置文件里的樣子:

<!-- ORDER SERVICE -->
<bean id="orderService"
 class="org.
     springframework.
     transaction.
     interceptor.
     TransactionProxyFactoryBean">
 <property name="transactionManager">
  <ref local="myTransactionManager"/>
 </property>
 <property name="target">
  <ref local="orderTarget"/>
 </property>
 <property name="transactionAttributes">
  <props>
   <prop key="find*">
  PROPAGATION_REQUIRED,readOnly,-OrderException
   </prop>
   <prop key="save*">
  PROPAGATION_REQUIRED,-OrderException
   </prop>
  </props>
 </property>
</bean>
<!-- ORDER TARGET PRIMARY BUSINESS OBJECT:
Hibernate implementation -->
<bean id="orderTarget"
     class="com.
        meagle.
        service.
        spring.
        OrderServiceSpringImpl">
 <property name="orderDAO">
  <ref local="orderDAO"/>
 </property>
</bean>
<!-- ORDER DAO OBJECT -->
<bean id="orderDAO"
     class="com.
        meagle.
        service.
        dao.
        hibernate.
        OrderHibernateDAO">
 <property name="sessionFactory">
  <ref local="mySessionFactory"/>
 </property>
</bean>


圖4是我們已經(jīng)連在一起的東西的一個概覽。它展示了每個對象是怎樣相關(guān)聯(lián)的和怎樣被Spring設(shè)置進其它對象中。把這幅圖和示例應(yīng)用中的Spring配置文件對比查看它們之間的關(guān)系。

圖4:這是Spring怎樣將在這個配置的基礎(chǔ)上裝配beans。

  這個例子使用一個TransactionProxyFactoryBean,它有一個為我們已經(jīng)定義了的事務(wù)管理者準(zhǔn)備的setter方法。這是一個有用的對象,它知道怎樣處理聲明的事務(wù)操作和你的服務(wù)對象。你可以通過transactionAttributes屬性定義事務(wù)怎樣被處理,transactionAttributes屬性為方法名定義模式和它們怎樣參與進一個事務(wù)。

TransactionProxyFactoryBean類也有一個為一個target準(zhǔn)備的setter,target將是一個到我們的叫作orderTarget的業(yè)務(wù)服務(wù)對象的引用。 orderTarget bean定義使用哪個業(yè)務(wù)服務(wù)對象并有一個指向setOrderDAO()的屬性。orderDAO bean將居于這個屬性中,orderDAO bean是我們的和持久層交流的DAO對象。

還有一個關(guān)于Spring和bean要注意的是bean能以兩種模式工作。這兩種模式被定義為singleton和prototype。一個bean默認的模式是singleton,意味著一個共享的bean的實例將被管理。這是用于無狀態(tài)操作--像一個無狀態(tài)會話bean將提供的那樣。當(dāng)bean由Spring提供時,prototype模式允許創(chuàng)建bean的新實例。你應(yīng)當(dāng)只有在每一個用戶都需要他們自己的bean的拷貝時才使用prototype模式。

  提 供一個服務(wù)定位器

既然我們已經(jīng)把我們的服務(wù)和我們的DAO連起來了,我們需要把我們的服務(wù)暴露給其它層。通常是一個像使用Struts或Swing這樣的用戶接口層里的代碼來使用這個服務(wù)。一個簡單的處理方法是使用一個服務(wù)定位器模式的類從一個Spring上下文中返回資源。這也可以靠引用bean ID通過Spring來直接完成。

這兒是一個在Struts Action中怎樣配置一個服務(wù)定位器的例子:

public abstract class BaseAction extends Action {
 private IOrderService orderService;
 public void setServlet(ActionServlet
                 actionServlet) {
  super.setServlet(actionServlet);
  ServletContext servletContext =
        actionServlet.getServletContext();
  WebApplicationContext wac =
   WebApplicationContextUtils.
     getRequiredWebApplicationContext(
                 servletContext);
   this.orderService = (IOrderService)
           wac.getBean("orderService");
 }
 protected IOrderService getOrderService() {
  return orderService;
 }
}

用戶接口層配置

示例應(yīng)用的用戶接口層使用Struts框架。這兒我們將討論當(dāng)為一個應(yīng)用分層時和Struts相關(guān)的部分。讓我們從在struts-config.xml文件里檢查一個Action配置開始。

<action path="/SaveNewOrder"
  type="com.meagle.action.SaveOrderAction"
  name="OrderForm"
  scope="request"
  validate="true"
  input="/NewOrder.jsp">
 <display-name>Save New Order</display-name>
 <exception key="error.order.save"
  path="/NewOrder.jsp"
  scope="request"
  type="com.meagle.exception.OrderException"/>
 <exception key="error.order.not.enough.money"
  path="/NewOrder.jsp"
  scope="request"
  type="com.
  meagle.
  exception.
  OrderMinimumAmountException"/>
 <forward name="success" path="/ViewOrder.jsp"/>
 <forward name="failure" path="/NewOrder.jsp"/>
</action>

SaveNewOrder Action被用來持久化一個用戶從用戶接口層提交的訂單。這是一個典型的Struts Action;然而,注意這個action的異常配置。這些Exceptions為我們的業(yè)務(wù)服務(wù)對象也在Spring 配置文件中配置了。當(dāng)這些異常被從業(yè)務(wù)層擲出我們能在我們的用戶接口里恰當(dāng)?shù)奶幚硭鼈儭5谝粋€異常,OrderException,當(dāng)在持久層里保存訂單對象失敗時將被這個action使用。這將引起事務(wù)回滾和通過業(yè)務(wù)對象傳遞把異常傳回給Struts層。OrderMinimumAmountException,在業(yè)務(wù)對象邏輯里的一個事務(wù)因為提交的訂單達不到最小訂單數(shù)量而失敗也將被處理。然后,事務(wù)將回滾和這個異常能被用戶接口層恰當(dāng)?shù)奶幚怼?

  最后一個連接步驟是使我們的表現(xiàn)層和我們的業(yè)務(wù)層交互。這已經(jīng)通過使用前面討論的服務(wù)定位器來完成了。服務(wù)層充當(dāng)一個到我們的業(yè)務(wù)邏輯和持久層的接口。這兒是 Struts中的SaveNewOrder Action可能怎樣使用一個服務(wù)定位器調(diào)用一個業(yè)務(wù)方法:

public ActionForward execute(
 ActionMapping mapping,
 ActionForm form,
 javax.servlet.http.HttpServletRequest request,
 javax.servlet.http.HttpServletResponse response)
 throws java.lang.Exception {
 OrderForm oForm = (OrderForm)form;
 // Use the form to build an Order object that
 // can be saved in the persistence layer.
 // See the full source code in the sample app.
 // Obtain the wired business service object
 // from the service locator configuration
 // in BaseAction.
 // Delegate the save to the service layer and
 // further upstream to save the Order object.
 getOrderService().saveNewOrder(order);
 oForm.setOrder(order);
 ActionMessages messages = new ActionMessages();
 messages.add(
   ActionMessages.GLOBAL_MESSAGE,
new ActionMessage(
   "message.order.saved.successfully"));
 saveMessages(request, messages);
 return mapping.findForward("success");
}

結(jié)論

這篇文章按照技術(shù)和架構(gòu)覆蓋了許多話題。從中而取出的主要思想是怎樣更好的給你的應(yīng)用程序分層:用戶接口層、持久邏輯層、和其它任何你需要的應(yīng)用層。這樣可以解耦你的代碼,允許添加新的代碼組件,使你的應(yīng)用在將來更易維護。這里覆蓋的技術(shù)能很好的解決這類的問題。不管怎樣,使用這樣的構(gòu)架可以讓你用其他技術(shù)代替現(xiàn)在的層。例如,你也許不想使用Hibernate持久化。因為你在你的DAO對象中編碼到接口,你能怎樣使用其它的技術(shù)或框架,比如 iBATIS,作為一個替代是顯而易見的。或者你可能用不同于Struts的框架替代你的UI層。改變UI層的實現(xiàn)不會直接影響你的業(yè)務(wù)邏輯層或者你的持久層。替換你的持久層不會影響你的UI邏輯或業(yè)務(wù)服務(wù)層。集成一個web應(yīng)用其實也不是一件煩瑣的工作,靠解耦你的各應(yīng)用層和用適當(dāng)?shù)目蚣芙M成它,它能變得更容易處理。

使用struts+spring+hibernate 組裝web應(yīng)用


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产精品亚洲综合第一区 | 91福利视频免费观看 | 九九热在线视频播放 | 国产视频国产 | 久久精品夜夜夜夜夜久久 | 男人爱看的网站 | 国产九九热 | 成年女人午夜毛片免费看 | 亚洲精品乱码一区二区在线观看 | 久久久久亚洲精品美女 | 99re热精品视频国产免费 | 五月天激情视频在线观看 | 中文字幕一区二区三区四区五区人 | 一区二区在线视频 | 在线播放国产精品 | 搡女人视频免费 | 成年人黄色在线观看 | 99精品热线在线观看免费视频 | 欧美一级毛片片aa视频 | 一级毛片特级毛片黄毛片 | 亚洲欧美成人综合久久久 | 99免费在线视频 | 亚洲高清中文字幕一区二区三区 | 最近中文字幕无吗高清视频 | 伊人久久欧美综合精品 | 国产色婷婷精品综合在线观看 | 精品国产第一国产综合精品 | 欧美另类69xxxxx视频 | 天天夜夜骑 | 涩涩的视频在线观看 | 99热在线精品观看 | 日韩欧美综合视频 | 久久99国产精品 | 97最新网址 | 久久只精品 | 国自产拍在线视频天天更新 | 久久九九影视 | 久久中文字幕免费 | 国产亚洲精品热视频在线观看 | 色老头一区二区三区 | 高清国产美女在线观看 |