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

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

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

    blog.Toby

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      130 隨筆 :: 2 文章 :: 150 評論 :: 0 Trackbacks
    多數(shù) IT 組織都必須解決三個主要問題: 1 .幫助組織減少成本 2 .增加并且保持客戶 3 .加快業(yè)務(wù)效率。完成這些問題一般都需要實現(xiàn)對多個業(yè)務(wù)系統(tǒng)的數(shù)據(jù)和業(yè)務(wù)邏輯的無縫訪問,也就是說,要實施系統(tǒng)集成工程,以便聯(lián)結(jié)業(yè)務(wù)流程、實現(xiàn)數(shù)據(jù)的訪問與共享。

    JpetStore 4.0 ibatis 的最新示例程序,基于 Struts MVC 框架(注:非傳統(tǒng) Struts 開發(fā)模式),以 ibatis 作為持久化層。該示例程序設(shè)計優(yōu)雅,層次清晰,可以學習以及作為一個高效率的編程模型參考。本文是在其基礎(chǔ)上,采用 Spring 對其中間層(業(yè)務(wù)層)進行改造。使開發(fā)量進一步減少,同時又擁有了 Spring 的一些好處…

    1. 前言
    JpetStore 4.0
    ibatis 的最新示例程序。 ibatis 是開源的持久層產(chǎn)品,包含 SQL Maps 2.0 Data Access Objects 2.0 框架。 JpetStore 示例程序很好的展示了如何利用 ibatis 來開發(fā)一個典型的 J2EE web 應(yīng)用程序。 JpetStore 有如下特點:

    • ibatis 數(shù)據(jù)層

    • POJO 業(yè)務(wù)層

    • POJO 領(lǐng)域類

    • Struts MVC

    • JSP 表示層

    以下是本文用到的關(guān)鍵技術(shù)介紹,本文假設(shè)您已經(jīng)對 Struts SpringFramewok , ibatis 有一定的了解,如果不是,請首先查閱附錄中的參考資料。

    • Struts 是目前 Java Web MVC 框架中不爭的王者。經(jīng)過長達五年的發(fā)展, Struts 已經(jīng)逐漸成長為一個穩(wěn)定、成熟的框架,并且占有了 MVC 框架中最大的市場份額。但是 Struts 某些技術(shù)特性上已經(jīng)落后于新興的 MVC 框架。面對 Spring MVC 、 Webwork2 這些設(shè)計更精密,擴展性更強的框架, Struts 受到了前所未有的挑戰(zhàn)。但站在產(chǎn)品開發(fā)的角度而言, Struts 仍然是最穩(wěn)妥的選擇。本文的原型例子 JpetStore 4.0 就是基于 Struts 開發(fā)的,但是不拘泥于 Struts 的傳統(tǒng)固定用法,例如只用了一個自定義 Action 類,并且在 form bean 類的定義上也是開創(chuàng)性的,令人耳目一新,稍后將具體剖析一下。

    • Spring Framework 實際上是 Expert One-on-One J2EE Design and Development 一書中所闡述的設(shè)計思想的具體實現(xiàn)。 Spring Framework 的功能非常多。包含 AOP ORM DAO 、 Context 、 Web MVC 等幾個部分組成。 Web 、 MVC 暫不用考慮, JpetStore 4.0 用的是更成熟的 Struts JSP ; DAO 由于目前 Hibernate JDO ibatis 的流行,也不考慮, JpetStore 4.0 用的就是 ibatis 。因此最需要用的是 AOP ORM 、 Context 。 Context 中,最重要的是 Beanfactory ,它能將接口與實現(xiàn)分開,非常強大。目前 AOP 應(yīng)用最成熟的還是在事務(wù)管理上。

    • ibatis 是一個功能強大實用的 SQL Map 工具,不同于其他 ORM 工具(如 hibernate ),它是將 SQL 語句映射成 Java 對象,而對于 ORM 工具,它的 SQL 語句是根據(jù)映射定義生成的。 ibatis SQL 開發(fā)的工作量和數(shù)據(jù)庫移植性上的讓步,為系統(tǒng)設(shè)計提供了更大的自由空間。有 ibatis 代碼生成的工具,可以根據(jù) DDL 自動生成 ibatis 代碼,能減少很多工作量。

    2. JpetStore 簡述

    2.1. 背景
    最初是 Sun 公司的 J2EE petstore ,其最主要目的是用于學習 J2EE ,但是其缺點也很明顯,就是過度設(shè)計了。接著 Oracle J2EE petstore 來比較各應(yīng)用服務(wù)器的性能。微軟推出了基于 .Net 平臺的 Pet shop ,用于競爭 J2EE petstore 。而 JpetStore 則是經(jīng)過改良的基于 struts 的輕便框架 J2EE web 應(yīng)用程序,相比來說, JpetStore 設(shè)計和架構(gòu)更優(yōu)良,各層定義清晰,使用了很多最佳實踐和模式,避免了很多 " 反模式 " ,如使用存儲過程,在 java 代碼中嵌入 SQL 語句,把 HTML 存儲在數(shù)據(jù)庫中等等。最新版本是 JpetStore 4.0 。

    2.2. JpetStore 開發(fā)運行環(huán)境的建立
    1
    、開發(fā)環(huán)境

    • Java SDK 1.4.2

    • Apache Tomcat 4.1.31

    • Eclipse-SDK-3.0.1-win32

    • HSQLDB 1.7.2

    2 Eclipse 插件

    • EMF SDK 2.0.1 Eclipse 建??蚣?, lomboz 插件需要,可以使用 runtime 版本。

    • lomboz 3.0 J2EE 插件,用來在 Eclipse 中開發(fā) J2EE 應(yīng)用程序

    • Spring IDE 1.0.3 Spring Bean 配置管理插件

    • xmlbuddy_2.0.10 :編輯 XML ,用免費版功能即可

    • tomcatPluginV3 tomcat 管理插件

    • Properties Editor :編輯 java 的屬性文件 , 并可以預(yù)覽以及自動存盤為 Unicode 格式。免去了手工或者 ANT 調(diào)用 native2ascii 的麻煩。

    3 、示例源程序

    • ibatis 示例程序 JpetStore 4.0 http://www.ibatis.com/jpetstore/jpetstore.html

    • 改造后的源程序( +spring )(源碼鏈接)

    2.3. 架構(gòu)

    1 JpetStore 架構(gòu)圖

    1 JPetStore 架構(gòu)圖,更詳細的內(nèi)容請參見 JPetStore 的白皮書。參照這個架構(gòu)圖,讓我們稍微剖析一下源代碼,得出 JpetStore 4.0 的具體實現(xiàn)圖(見圖 2 ),思路一下子就豁然開朗了。前言中提到的非傳統(tǒng)的 struts 開發(fā)模式,關(guān)鍵就在 struts Action 類和 form bean 類上。

    struts Action 類只有一個: BeanAction 。沒錯,確實是一個!與傳統(tǒng)的 struts 編程方式很不同。再仔細研究 BeanAction 類,發(fā)現(xiàn)它其實是一個通用類,利用反射原理,根據(jù) URL 來決定調(diào)用 formbean 的哪個方法。 BeanAction 大大簡化了 struts 的編程模式,降低了對 struts 的依賴(與 struts 以及 WEB 容器有關(guān)的幾個類都放在 com.ibatis.struts 包下,其它的類都可以直接復(fù)用)。利用這種模式,我們會很容易的把它移植到新的框架如 JSF , spring

    這樣重心就轉(zhuǎn)移到 form bean 上了,它已經(jīng)不是普通意義上的 form bean 了。查看源代碼,可以看到它不僅僅有數(shù)據(jù)和校驗 / 重置方法,而且已經(jīng)具有了行為,從這個意義上來說,它更像一個 BO(Business Object) 。這就是前文講到的, BeanAction 類利用反射原理,根據(jù) URL 來決定調(diào)用 form bean 的哪個方法(行為)。 form bean 的這些方法的簽名很簡單,例如:

    												
    														
    																?

    												
    														
    																 public String myActionMethod() {

    												
    														
    																
    																		?? //..work

    												
    														
    																
    																		?? return "success";

    												
    														
    																 }

    												
    														
    																
    																
    														
    														
    																

    方法的返回值直接就是字符串,對應(yīng)的是 forward 的名稱,而不再是 ActionForward 對象,創(chuàng)建 ActionForward 對象的任務(wù)已經(jīng)由 BeanAction 類代勞了。

    另外,程序還提供了 ActionContext 工具類,該工具類封裝了 request 、 response 、 form parameters 、 request attributes 、 session attributes application attributes 中的數(shù)據(jù)存取操作,簡單而線程安全, form bean 類使用該工具類可以進一步從表現(xiàn)層框架解耦。

    在這里需要特別指出的是, BeanAction 類是對 struts 擴展的一個有益嘗試,雖然提供了非常好的應(yīng)用開發(fā)模式,但是它還非常新,一直在發(fā)展中。

    2 JpetStore 4.0 具體實現(xiàn)

    2.4. 代碼剖析
    下面就讓我們開始進一步分析 JpetStore4.0 的源代碼,為下面的改造鋪路。

    • BeanAction.java 是唯一一個 Struts action 類,位于 com.ibatis.struts 包下。正如上文所言,它是一個通用的控制類,利用反射機制,把控制轉(zhuǎn)移到 form bean 的某個方法來處理。詳細處理過程參考其源代碼,簡單明晰。

    ·???????? Form bean 類位于 com.ibatis.jpetstore.presentation 包下,命名規(guī)則為 ***Bean Form bean 類全部繼承于 BaseBean 類,而 BaseBean 類實際繼承于 ActionForm ,因此, Form bean 類就是 Struts ActionForm Form bean 類的屬性數(shù)據(jù)就由 struts 框架自動填充。而實際上, JpetStore4.0 擴展了 struts ActionForm 的應(yīng)用: Form bean 類還具有行為,更像一個 BO, 其行為(方法)由 BeanAction 根據(jù)配置( struts-config.xml )的 URL 來調(diào)用。雖然如此,我們還是把 Form bean 類定位于表現(xiàn)層。

    Struts-config.xml 的配置里有 3 種映射方式,來告訴 BeanAction 把控制轉(zhuǎn)到哪個 form bean 對象的哪個方法來處理。

    以這個請求連接為例 http://localhost/jpetstore4/shop/viewOrder.do

    1. URL Pattern

    												
    														
    																?

    												
    														
    																
    																		??? <action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"

    												
    														
    																
    																		??? name="orderBean" scope="session"

    												
    														
    																
    																		??? validate="false">

    												
    														
    																
    																		??? <forward name="success" path="/order/ViewOrder.jsp"/>

    												
    														
    																
    																		? </action>

    												
    														
    																
    																		? 
    																
    														
    														
    																

    此種方式表示,控制將被轉(zhuǎn)發(fā)到 "orderBean" 這個 form bean 對象 "viewOrder" 方法(行為)來處理。方法名取 "path" 參數(shù)的以 "/" 分隔的最后一部分。

    2. Method Parameter

    												
    														
    																?

    												
    														
    																
    																		??? <action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"

    												
    														
    																
    																		??? name="orderBean" parameter="viewOrder" scope="session"

    												
    														
    																
    																		??? validate="false">

    												
    														
    																
    																		??? <forward name="success" path="/order/ViewOrder.jsp"/>

    												
    														
    																
    																		? </action>

    												
    														
    																
    																		? 
    																
    														
    														
    																

    此種方式表示,控制將被轉(zhuǎn)發(fā)到 "orderBean" 這個 form bean 對象的 "viewOrder" 方法(行為)來處理。配置中的 "parameter" 參數(shù)表示 form bean 類上的方法。 "parameter" 參數(shù)優(yōu)先于 "path" 參數(shù)。

    3. No Method call

    												
    														
    																?

    												
    														
    																
    																		??? <action path="/shop/viewOrder" type="com.ibatis.struts.BeanAction"

    												
    														
    																
    																		??? name="orderBean" parameter="*" scope="session"

    												
    														
    																
    																		??? validate="false">

    												
    														
    																
    																		??? <forward name="success" path="/order/ViewOrder.jsp"/>

    												
    														
    																
    																		? </action>

    												
    														
    																
    																		? 
    																
    														
    														
    																

    此種方式表示, form bean 上沒有任何方法被調(diào)用。如果存在 "name" 屬性,則 struts 把表單參數(shù)等數(shù)據(jù)填充到 form bean 對象后,把控制轉(zhuǎn)發(fā)到 "success" 。否則,如果 name 為空,則直接轉(zhuǎn)發(fā)控制到 "success"

    這就相當于 struts 內(nèi)置的 org.apache.struts.actions.ForwardAction 的功能

    												
    														
    																?

    												
    														
    																 <action path="/shop/viewOrder" type="org.apache.struts.actions.ForwardAction"

    												
    														
    																
    																		??? parameter="/order/ViewOrder.jsp " scope="session" validate="false">

    												
    														
    																 </action>

    												
    														
    																
    																
    														
    														
    																

    • Service 類位于 com.ibatis.jpetstore.service 包下,屬于業(yè)務(wù)層。這些類封裝了業(yè)務(wù)以及相應(yīng)的事務(wù)控制。 Service 類由 form bean 類來調(diào)用。

    • com.ibatis.jpetstore.persistence.iface 包下的類是 DAO 接口,屬于業(yè)務(wù)層,其屏蔽了底層的數(shù)據(jù)庫操作,供具體的 Service 類來調(diào)用。 DaoConfig 類是工具類( DAO 工廠類), Service 類通過 DaoConfig 類來獲得相應(yīng)的 DAO 接口,而不用關(guān)心底層的具體數(shù)據(jù)庫操作,實現(xiàn)了如圖 2 { 耦合 2} 的解耦。

    • com.ibatis.jpetstore.persistence.sqlmapdao 包下的類是對應(yīng) DAO 接口的具體實現(xiàn),在 JpetStore4.0 中采用了 ibatis 來實現(xiàn) ORM 。這些實現(xiàn)類繼承 BaseSqlMapDao 類,而 BaseSqlMapDao 類則繼承 ibatis DAO 框架中的 SqlMapDaoTemplate 類。 ibatis 的配置文件存放在 com.ibatis.jpetstore.persistence.sqlmapdao.sql 目錄下。這些類和配置文件位于數(shù)據(jù)層

    • Domain 類位于 com.ibatis.jpetstore.domain 包下,是普通的 javabean 。在這里用作數(shù)據(jù)傳輸對象( DTO ),貫穿視圖層、業(yè)務(wù)層和數(shù)據(jù)層,用于在不同層之間傳輸數(shù)據(jù)。

    剩下的部分就比較簡單了,請看具體的源代碼,非常清晰。

    2.5. 需要改造的地方
    JpetStore4.0
    的關(guān)鍵就在 struts Action 類和 form bean 類上,這也是其精華之一(雖然該實現(xiàn)方式是試驗性,待擴充和驗證),在此次改造中我們要保留下來,即控制層一點不變,表現(xiàn)層獲取相應(yīng)業(yè)務(wù)類的方式變了(要加載 spring 環(huán)境),其它保持不變。要特別關(guān)注的改動是業(yè)務(wù)層和持久層,幸運的是 JpetStore4.0 設(shè)計非常好,需要改動的地方非常少,而且由模式可循,如下:

    1. 業(yè)務(wù)層和數(shù)據(jù)層用 Spring BeanFactory 機制管理。

    2. 業(yè)務(wù)層的事務(wù)由 spring aop 通過聲明來完成。

    3. 表現(xiàn)層( form bean )獲取業(yè)務(wù)類的方法改由自定義工廠類來實現(xiàn)(加載 spring 環(huán)境)。

    3. JPetStore 的改造

    3.1. 改造后的架構(gòu)


    其中紅色部分是要增加的部分,藍色部分是要修改的部分。下面就讓我們逐一剖析。

    3.2. Spring Context 的加載
    為了在 Struts 中加載 Spring Context ,一般會在 struts-config.xml 的最后添加如下部分:

    												
    														
    																?

    												
    														
    																<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">

    												
    														
    																<set-property property="contextConfigLocation"

    												
    														
    																value="/WEB-INF/applicationContext.xml" />

    												
    														
    																</plug-in>

    Spring 在設(shè)計時就充分考慮到了與 Struts 的協(xié)同工作,通過內(nèi)置的 Struts Plug-in 在兩者之間提供了良好的結(jié)合點。但是,因為在這里我們一點也不改動 JPetStore 的控制層 ( 這是 JpetStore4.0 的精華之一 ) ,所以本文不準備采用此方式來加載 ApplicationContext 。我們利用的是 spring framework BeanFactory 機制 , 采用自定義的工具類( bean 工廠類)來加載 spring 的配置文件,從中可以看出 Spring 有多靈活,它提供了各種不同的方式來使用其不同的部分 / 層次,您只需要用你想用的,不需要的部分可以不用。

    具體的來說,就是在 com.ibatis.spring 包下創(chuàng)建 CustomBeanFactory 類, spring 的配置文件 applicationContext.xml 也放在這個目錄下。以下就是該類的全部代碼,很簡單:

    												
    														
    																?

    												
    														
    																public final class CustomBeanFactory {

    												
    														
    																
    																		???????? static XmlBeanFactory factory = null;

    												
    														
    																
    																		???????? static {

    												
    														
    																
    																		???????????????? Resource is = new

    												
    														
    																InputStreamResource( CustomBeanFactory.class.getResourceAsStream("applicationContext.xml"));

    												
    														
    																
    																		???????????????? factory = new XmlBeanFactory(is);?????????????????? 

    												
    														
    																
    																		???????? }

    												
    														
    																
    																		???????? public static Object getBean(String beanName){

    												
    														
    																
    																		???????????????? return factory.getBean(beanName);

    												
    														
    																
    																		???????? }

    												
    														
    																}

    實際上就是封裝了 Spring XMLBeanFactory 而已,并且 Spring 的配置文件只需要加載一次,以后就可以直接用 CustomBeanFactory.getBean("someBean") 來獲得需要的對象了 ( 例如 someBean) ,而不需要知道具體的類。 CustomBeanFactory 類用于 { 耦合 1} 的解耦。

    CustomBeanFactory 類在本文中只用于表現(xiàn)層的 form bean 對象獲得 service 類的對象,因為我們沒有把 form bean 對象配置在 applicationContext.xml 中。但是,為什么不把表現(xiàn)層的 form bean 類也配置起來呢,這樣就用不著這 CustomBeanFactory 個類了, Spring 會幫助我們創(chuàng)建需要的一切?問題的答案就在于 form bean 類是 struts ActionForm 類!如果大家熟悉 struts ,就會知道 ActionForm 類是 struts 自動創(chuàng)建的:在一次請求中, struts 判斷,如果 ActionForm 實例不存在,就創(chuàng)建一個 ActionForm 對象,把客戶提交的表單數(shù)據(jù)保存到 ActionForm 對象中。因此 formbean 類的對象就不能由 spring 來創(chuàng)建,但是 service 類以及數(shù)據(jù)層的 DAO 類可以,所以只有他們在 spring 中配置。

    所以,很自然的,我們就創(chuàng)建了 CustomBeanFactory 類,在表現(xiàn)層來銜接 struts spring 。就這么簡單,實現(xiàn)了另一種方式的 { 耦合一 } 的解耦。

    3.3. 表現(xiàn)層
    面分析到, struts spring 是在表現(xiàn)層銜接起來的,那么表現(xiàn)層就要做稍微的更改,即所需要的 service 類的對象創(chuàng)建上。以表現(xiàn)層的 AccountBean 類為例:

    原來的源代碼如下

    												
    														
    																?

    												
    														
    																
    																		??? private static final AccountService accountService = AccountService.getInstance();

    												
    														
    																
    																		? private static final CatalogService catalogService = CatalogService.getInstance();

    												
    														
    																
    																		? 
    																
    														
    														
    																

    改造后的源代碼如下

    												
    														
    																?

    												
    														
    																
    																		? private static final AccountService accountService = (AccountService)CustomBeanFactory.getBean("AccountService");

    												
    														
    																
    																		? private static final CatalogService catalogService = (CatalogService)CustomBeanFactory.getBean("CatalogService");

    其他的幾個 presentation 類以同樣方式改造。這樣,表現(xiàn)層就完成了。關(guān)于表現(xiàn)層的其它部分如 JSP 等一概不動。也許您會說,沒有看出什么特別之處的好處???你還是額外實現(xiàn)了一個工廠類。別著急,帷幕剛剛開啟, spring 是在表現(xiàn)層引入,但您發(fā)沒發(fā)現(xiàn):

    • presentation 類僅僅面向 service 類的接口編程,具體 "AccountService" 是哪個實現(xiàn)類, presentation 類不知道,是在 spring 的配置文件里配置。(本例中,為了最大限度的保持原來的代碼不作變化,沒有抽象出接口)。 Spring 鼓勵面向接口編程,因為是如此的方便和自然,當然您也可以不這么做。

    • CustomBeanFactory 這個工廠類為什么會如此簡單,因為其直接使用了 Spring BeanFactory 。 Spring 從其核心而言,是一個 DI 容器,其設(shè)計哲學是提供一種無侵入式的高擴展性的框架。為了實現(xiàn)這個目標, Spring 大量引入了 Java Reflection 機制,通過動態(tài)調(diào)用的方式避免硬編碼方式的約束,并在此基礎(chǔ)上建立了其核心組件 BeanFactory ,以此作為其依賴注入機制的實現(xiàn)基礎(chǔ)。 org.springframework.beans 包中包括了這些核心組件的實現(xiàn)類,核心中的核心為 BeanWrapper BeanFactory 類。

    3.4. 持久層
    在討論業(yè)務(wù)層之前,我們先看一下持久層,如下圖所示:


    在上文中,我們把 iface 包下的 DAO 接口歸為業(yè)務(wù)層,在這里不需要做修改。 ibatis sql 配置文件也不需要改。要改的是 DAO 實現(xiàn)類,并在 spring 的配置文件中配置起來。

    1 、修改基類

    所有的 DAO 實現(xiàn)類都繼承于 BaseSqlMapDao 類。修改 BaseSqlMapDao 類如下:

    												
    														
    																?

    												
    														
    																public class BaseSqlMapDao extends SqlMapClientDaoSupport {

    												
    														
    																
    																		? protected static final int PAGE_SIZE = 4;

    												
    														
    																
    																		? protected SqlMapClientTemplate smcTemplate = this.getSqlMapClientTemplate();

    												
    														
    																
    																		? public BaseSqlMapDao() { 

    												
    														
    																
    																		???????? }

    												
    														
    																}

    使 BaseSqlMapDao 類改為繼承于 Spring 提供的 SqlMapClientDaoSupport 類,并定義了一個保護屬性 smcTemplate ,其類型為 SqlMapClientTemplate 。關(guān)于 SqlMapClientTemplate 類的詳細說明請參照附錄中的 "Spring 中文參考手冊 "

    2 、修改 DAO 實現(xiàn)類

    所有的 DAO 實現(xiàn)類還是繼承于 BaseSqlMapDao 類,實現(xiàn)相應(yīng)的 DAO 接口,但其相應(yīng)的 DAO 操作委托 SqlMapClientTemplate 來執(zhí)行,以 AccountSqlMapDao 類為例,部分代碼如下:

    												
    														
    																?

    												
    														
    																
    																		??? public List getUsernameList() {

    												
    														
    																
    																		??? return smcTemplate.queryForList("getUsernameList", null);

    												
    														
    																
    																		? }

    												
    														
    																
    																		? public Account getAccount(String username, String password) {

    												
    														
    																
    																		??? Account account = new Account();

    												
    														
    																
    																		??? account.setUsername(username);

    												
    														
    																
    																		? 
    																		??account.setPassword(password);

    												
    														
    																
    																		??? return (Account) smcTemplate.queryForObject("getAccountByUsernameAndPassword", account);

    												
    														
    																
    																		? }

    												
    														
    																
    																		? public void insertAccount(Account account) {

    												
    														
    																
    																		? 
    																		?????? smcTemplate.update("insertAccount", account);

    												
    														
    																
    																		? 
    																		?????? smcTemplate.update("insertProfile", account);

    												
    														
    																
    																		? 
    																		?????? smcTemplate.update("insertSignon", account);

    												
    														
    																
    																		? }

    												
    														
    																
    																		? 
    																
    														
    														
    																

    就這么簡單,所有函數(shù)的簽名都是一樣的,只需要查找替換就可以了!

    3 、除去工廠類以及相應(yīng)的配置文件

    除去 DaoConfig.java 這個 DAO 工廠類和相應(yīng)的配置文件 dao.xml ,因為 DAO 的獲取現(xiàn)在要用 spring 來管理。

    4 、 DAO Spring 中的配置( applicationContext.xml

    												
    														
    																?

    												
    														
    																
    																		??? <bean id="dataSource" 

    												
    														
    																
    																		????????class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    												
    														
    																
    																		??????? <property name="driverClassName">

    												
    														
    																
    																		??????????? <value>org.hsqldb.jdbcDriver</value>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??????? <property name="url">

    												
    														
    																
    																		??????????? <value>jdbc:hsqldb:hsql://localhost/xdb</value>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??????? <property name="username">

    												
    														
    																
    																		??????????? <value>sa</value>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??????? <property name="password">

    												
    														
    																
    																		??????????? <value></value>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??? </bean>??? 

    												
    														
    																
    																		????<!-- ibatis sqlMapClient config -->

    												
    														
    																
    																		??? <bean id="sqlMapClient" 

    												
    														
    																
    																		????????class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

    												
    														
    																
    																		??????? <property name="configLocation">

    												
    														
    																
    																		??????????? <value> 

    												
    														
    																
    																		????????????????classpath:com\ibatis\jpetstore\persistence\sqlmapdao\sql\sql-map-config.xml

    												
    														
    																
    																		??????????? </value>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??????? <property name="dataSource">

    												
    														
    																
    																		??????????? <ref bean="dataSource"/>

    												
    														
    																
    																		??????? </property>??? 

    												
    														
    																
    																		????</bean>

    												
    														
    																
    																		??? <!-- Transactions -->

    												
    														
    																
    																		?? 
    																		?<bean id="TransactionManager" 

    												
    														
    																
    																		????????class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    												
    														
    																
    																		??????? <property name="dataSource">

    												
    														
    																
    																		??????????? <ref bean="dataSource"/>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??? </bean>

    												
    														
    																
    																		??? <!-- persistence layer -->

    												
    														
    																
    																		??? <bean id="AccountDao" 

    												
    														
    																
    																		????????class="com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao">

    												
    														
    																
    																		??????? <property name="sqlMapClient">

    												
    														
    																
    																		??????????? <ref local="sqlMapClient"/>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??? </bean>

    												
    														
    																
    																		??? 
    																
    														
    														
    																

    具體的語法請參照附錄中的 "Spring 中文參考手冊 " 。在這里只簡單解釋一下:

    1. 我們首先創(chuàng)建一個數(shù)據(jù)源 dataSource ,在這里配置的是 hsqldb 數(shù)據(jù)庫。如果是 ORACLE 數(shù)據(jù)庫, driverClassName 的值是 "oracle.jdbc.driver.OracleDriver" , URL 的值類似于 "jdbc:oracle:thin:@wugfMobile:1521:cdcf" 。數(shù)據(jù)源現(xiàn)在由 spring 來管理,那么現(xiàn)在我們就可以去掉 properties 目錄下 database.properties 這個配置文件了;還有不要忘記修改 sql-map-config.xml ,去掉 <properties resource="properties/database.properties"/> 對它的引用。

    2. sqlMapClient 節(jié)點。這個是針對 ibatis SqlMap SqlMapClientFactoryBean 配置。實際上配置了一個 sqlMapClient 的創(chuàng)建工廠類。 configLocation 屬性配置了 ibatis 映射文件的名稱。 dataSource 屬性指向了使用的數(shù)據(jù)源,這樣所有使用 sqlMapClient DAO 都默認使用了該數(shù)據(jù)源,除非在 DAO 的配置中另外顯式指定。

    3. TransactionManager 節(jié)點。定義了事務(wù),使用的是 DataSourceTransactionManager

    4. 下面就可以定義 DAO 節(jié)點了,如 AccountDao ,它的實現(xiàn)類是 com.ibatis.jpetstore.persistence.sqlmapdao.AccountSqlMapDao ,使用的 SQL 配置從 sqlMapClient 中讀取,數(shù)據(jù)庫連接沒有特別列出,那么就是默認使用 sqlMapClient 配置的數(shù)據(jù)源 datasource

    這樣,我們就把持久層改造完了,其他的 DAO 配置類似于 AccountDao 。怎么樣?簡單吧。這次有接口了:) AccountDao 接口- >AccountSqlMapDao 實現(xiàn)。

    3.5. 業(yè)務(wù)層
    業(yè)務(wù)層的位置以及相關(guān)類,如下圖所示:


    在這個例子中只有 3 個業(yè)務(wù)類,我們以 OrderService 類為例來改造,這個類是最復(fù)雜的,其中涉及了事務(wù)。

    1 、在 ApplicationContext 配置文件中增加 bean 的配置:

    												
    														
    																?

    												
    														
    																
    																		??? <bean id="OrderService" 

    												
    														
    																
    																		????????class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

    												
    														
    																
    																		??????? <property name="transactionManager">

    												
    														
    																
    																		??????????? <ref local="TransactionManager"></ref>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??????? <property name="target">

    												
    														
    																
    																		??????????? <bean class="com.ibatis.jpetstore.service.OrderService">

    												
    														
    																
    																		??????????????? <property name="itemDao">

    												
    														
    																
    																		???? 
    																		???????????????<ref bean="ItemDao"/>

    												
    														
    																
    																		??????????????? </property>

    												
    														
    																
    																		??????????????? <property name="orderDao">

    												
    														
    																
    																		??????????????????? <ref bean="OrderDao"/>

    												
    														
    																
    																		??????????????? </property>

    												
    														
    																
    																		??????????????? <property name="sequenceDao">

    												
    														
    																
    																		??????????????????? <ref bean="SequenceDao"/>

    												
    														
    																
    																		??????????????? </property>

    												
    														
    																
    																		??????????? </bean>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??????? <property name="transactionAttributes">

    												
    														
    																
    																		??????????? <props>

    												
    														
    																
    																		??????????????? <prop key="insert*">PROPAGATION_REQUIRED</prop>

    												
    														
    																
    																		??????????? </props>

    												
    														
    																
    																		??????? </property>

    												
    														
    																
    																		??? </bean>

    												
    														
    																
    																		??? 
    																
    														
    														
    																

    定義了一個 OrderService ,還是很容易懂的。為了簡單起見,使用了嵌套 bean ,其實現(xiàn)類是 com.ibatis.jpetstore.service.OrderService ,分別引用了 ItemDao , OrderDao , SequenceDao 。該 bean insert* 實現(xiàn)了事務(wù)管理 (AOP 方式 ) 。 TransactionProxyFactoryBean 自動創(chuàng)建一個事務(wù) advisor , advisor 包括一個基于事務(wù)屬性的 pointcut, 因此只有事務(wù)性的方法被攔截。

    2 、業(yè)務(wù)類的修改

    OrderService 為例:

    												
    														
    																?

    												
    														
    																public class OrderService {

    												
    														
    																?

    												
    														
    																
    																		?? /* Private Fields */

    												
    														
    																
    																		? private ItemDao itemDao;

    												
    														
    																
    																		? private OrderDao orderDao;

    												
    														
    																
    																		? private SequenceDao sequenceDao;

    												
    														
    																?

    												
    														
    																
    																		? /* Constructors */

    												
    														
    																?

    												
    														
    																
    																		? public OrderService() {

    												
    														
    																
    																		? }

    												
    														
    																?

    												
    														
    																/**

    												
    														
    																 * @param itemDao 要設(shè)置的 itemDao。

    												
    														
    																 */

    												
    														
    																public final void setItemDao(ItemDao itemDao) {

    												
    														
    																
    																		???????? this.itemDao = itemDao;

    												
    														
    																}

    												
    														
    																/**

    												
    														
    																 * @param orderDao 要設(shè)置的 orderDao。

    												
    														
    																 */

    												
    														
    																public final void setOrderDao(OrderDao orderDao) {

    												
    														
    																
    																		???????? this.orderDao = orderDao;

    												
    														
    																}

    												
    														
    																/**

    												
    														
    																 * @param sequenceDao 要設(shè)置的 sequenceDao。

    												
    														
    																 */

    												
    														
    																public final void setSequenceDao(SequenceDao sequenceDao) {

    												
    														
    																
    																		???????? this.sequenceDao = sequenceDao;

    												
    														
    																}

    												
    														
    																//剩下的部分

    												
    														
    																……
    														
    														
    																.

    												
    														
    																}

    紅色部分為修改部分。 Spring 采用的是 Type2 的設(shè)置依賴注入,所以我們只需要定義屬性和相應(yīng)的設(shè)值函數(shù)就可以了, ItemDao , OrderDao , SequenceDao 的值由 spring 在運行期間注入。構(gòu)造函數(shù)就可以為空了,另外也不需要自己編寫代碼處理事務(wù)了(事務(wù)在配置中聲明), daoManager.startTransaction(); 等與事務(wù)相關(guān)的語句也可以去掉了。和原來的代碼比較一下,是不是處理精簡了很多!可以更關(guān)注業(yè)務(wù)的實現(xiàn)。

    4. 結(jié)束語
    ibatis
    是一個功能強大實用的 SQL Map 工具,可以直接控制 SQL, 為系統(tǒng)設(shè)計提供了更大的自由空間。其提供的最新示例程序 JpetStore 4.0, 設(shè)計優(yōu)雅,應(yīng)用了迄今為止很多最佳實踐和設(shè)計模式,非常適于學習以及在此基礎(chǔ)上創(chuàng)建輕量級的 J2EE WEB 應(yīng)用程序。 JpetStore 4.0 是基于 struts 的,本文在此基礎(chǔ)上,最大程度保持了原有設(shè)計的精華以及最小的代碼改動量,在業(yè)務(wù)層和持久化層引入了 Spring 。在您閱讀了本文以及改造后的源代碼后,會深切的感受到 Spring 帶來的種種好處:自然的面向接口的編程,業(yè)務(wù)對象的依賴注入,一致的數(shù)據(jù)存取框架和聲明式的事務(wù)處理,統(tǒng)一的配置文件…更重要的是 Spring 既是全面的又是模塊化的, Spring 有分層的體系結(jié)構(gòu),這意味著您能選擇僅僅使用它任何一個獨立的部分,就像本文,而它的架構(gòu)又是內(nèi)部一致。

    參考資料

    ??????作者Blog:http://blog.csdn.net/yanwp/

    posted on 2006-04-21 14:47 渠上月 閱讀(340) 評論(0)  編輯  收藏 所屬分類: java tips
    主站蜘蛛池模板: 又黄又爽的视频免费看| 亚洲色图校园春色| 一本色道久久88亚洲精品综合| 国产精品一区二区三区免费| 在线观看免费人成视频色| 亚洲精品无码永久在线观看你懂的| 亚洲国产乱码最新视频| 可以免费观看的国产视频| 免费人成视频在线观看视频| 亚洲xxxxxx| 日韩精品无码专区免费播放| 国产啪亚洲国产精品无码| 亚洲第一成年网站视频| 91免费国产自产地址入| 亚洲色偷偷偷鲁综合| AV激情亚洲男人的天堂国语| 中文字幕乱码免费视频| 久久久久亚洲av无码尤物| 一区在线免费观看| 国产不卡免费视频| 在线精品亚洲一区二区| 69视频免费观看l| 亚洲AV永久青草无码精品| jizz免费观看视频| 又粗又大又长又爽免费视频| 亚洲免费福利在线视频| 51精品视频免费国产专区| 亚洲国产第一站精品蜜芽| 一级特级女人18毛片免费视频| 国产成人免费全部网站 | 亚洲AV无码一区二区乱孑伦AS| 日韩在线视频线视频免费网站| 日韩免费高清视频网站| 亚洲高清有码中文字| 在线精品一卡乱码免费| 亚洲精品中文字幕无码AV| 国产高清不卡免费视频| 亚洲av永久无码精品古装片| 中出五十路免费视频| 一本久久a久久精品亚洲| 一级看片免费视频囗交|