1 Spring框架
1.1 Spring框架
??? Spring框架是一個分層架構(gòu),由7個定義良好的模塊組成。Spring 模塊構(gòu)建在核心容器之上,核心容器定義了創(chuàng)建、配置和管理 bean 的方式,如圖1所示。

??? 組成Spring框架的每個模塊(或組件)都可以單獨存在,或者與其他一個或多個模塊聯(lián)合實現(xiàn)。每個模塊的功能如下:
????? ? 核心容器:核心容器提供Spring框架的基本功能。核心容器的主要組件是BeanFactory,它是工廠模式的實現(xiàn)。BeanFactory使用控制反轉(zhuǎn)(IOC)模式將應(yīng)用程序的配置和依賴性規(guī)范與實際的應(yīng)用程序代碼分開。
????? ? Spring上下文: Spring上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業(yè)服務(wù),例如 JNDI、EJB、電子郵件、國際化、校驗和調(diào)度功能。
????? ? Spring AOP:通過配置管理特性,Spring AOP 模塊直接將面向方面的編程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何對象支持 AOP。Spring AOP 模塊為基于 Spring 的應(yīng)用程序中的對象提供了事務(wù)管理服務(wù)。通過使用 Spring AOP,不用依賴 EJB 組件,就可以將聲明性事務(wù)管理集成到應(yīng)用程序中。
????? ? Spring DAO:JDBC DAO抽象層提供了有意義的異常層次結(jié)構(gòu),可用該結(jié)構(gòu)來管理異常處理和不同數(shù)據(jù)庫供應(yīng)商拋出的錯誤消息。異常層次結(jié)構(gòu)簡化了錯誤處理,并且極大地降低了需要編寫的異常代碼數(shù)量(例如打開和關(guān)閉連接)。Spring DAO的面向JDBC的異常遵從通用的DAO異常層次結(jié)構(gòu)。
????? ? Spring ORM: Spring框架插入了若干個ORM框架,從而提供了ORM的對象關(guān)系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務(wù)和 DAO 異常層次結(jié)構(gòu)。
????? ? Spring Web 模塊:Web 上下文模塊建立在應(yīng)用程序上下文模塊之上,為基于 Web 的應(yīng)用程序提供了上下文。所以,Spring 框架支持與 Jakarta Struts 的集成。Web 模塊還簡化了處理多部分請求以及將請求參數(shù)綁定到域?qū)ο蟮墓ぷ鳌?/p>
????? ? Spring MVC 框架:MVC 框架是一個全功能的構(gòu)建 Web 應(yīng)用程序的 MVC 實現(xiàn)。通過策略接口,MVC 框架變成為高度可配置的,MVC 容納了大量視圖技術(shù),其中包括 JSP、Velocity、Tiles、iText 和 POI。
??? Spring框架的功能可以用在任何 J2EE 服務(wù)器中,大多數(shù)功能也適用于不受管理的環(huán)境。Spring 的核心要點是:支持不綁定到特定 J2EE 服務(wù)的可重用業(yè)務(wù)和數(shù)據(jù)訪問對象。毫無疑問,這樣的對象可以在不同 J2EE 環(huán)境 (Web 或 EJB)、獨立應(yīng)用程序、測試環(huán)境之間重用。
1.2 IOC 和 AOP
??? 控制反轉(zhuǎn)模式(也稱作依賴性介入)的基本概念是:不創(chuàng)建對象,但是描述創(chuàng)建它們的方式。在代碼中不直接與對象和服務(wù)連接,但在配置文件中描述哪一個組件需要哪一項服務(wù)。容器(在 Spring 框架中是 IOC 容器)負責將這些聯(lián)系在一起。
??? 在典型的 IOC 場景中,容器創(chuàng)建了所有對象,并設(shè)置必要的屬性將它們連接在一起,決定什么時間調(diào)用方法。下表列出了 IOC 的一個實現(xiàn)模式。

Spring框架的 IOC 容器采用類型 2 和類型3實現(xiàn)。
1.2.1 面向切方的編程
??? 面向切面的編程,即AOP,是一種編程技術(shù),它允許程序員對橫切關(guān)注點或橫切典型的職責分界線的行為(例如日志和事務(wù)管理)進行模塊化。AOP的核心構(gòu)造是切面,它將那些影響多個類的行為封裝到可重用的模塊中。
??? AOP和IOC是補充性的技術(shù),它們都運用模塊化方式解決企業(yè)應(yīng)用程序開發(fā)中的復雜問題。在典型的面向?qū)ο箝_發(fā)方式中,可能要將日志記錄語句放在所有方法和Java類中才能實現(xiàn)日志功能。在AOP方式中,可以反過來將日志服務(wù)模塊化,并以聲明的方式將它們應(yīng)用到需要日志的組件上。當然,優(yōu)勢就是Java類不需要知道日志服務(wù)的存在,也不需要考慮相關(guān)的代碼。所以,用Spring AOP編寫的應(yīng)用程序代碼是松散耦合的。
??? AOP的功能完全集成到了Spring事務(wù)管理、日志和其他各種特性的上下文中。
1.3 IOC容器
??? Spring設(shè)計的核心是?org.springframework.beans?包,它的設(shè)計目標是與 JavaBean 組件一起使用。這個包通常不是由用戶直接使用,而是由服務(wù)器將其用作其他多數(shù)功能的底層中介。下一個最高級抽象是??BeanFactory?接口,它是工廠設(shè)計模式的實現(xiàn),允許通過名稱創(chuàng)建和檢索對象。BeanFactory?也可以管理對象之間的關(guān)系。
??? BeanFactory?支持兩個對象模型。
·???????單例?模型提供了具有特定名稱的對象的共享實例,可以在查詢時對其進行檢索。Singleton 是默認的也是最常用的對象模型。對于無狀態(tài)服務(wù)對象很理想。
·???????原型?模型確保每次檢索都會創(chuàng)建單獨的對象。在每個用戶都需要自己的對象時,原型模型最適合。
??? bean工廠的概念是Spring作為IOC容器的基礎(chǔ)。IOC將處理事情的責任從應(yīng)用程序代碼轉(zhuǎn)移到框架。正如我將在下一個示例中演示的那樣,Spring框架使用JavaBean屬性和配置數(shù)據(jù)來指出必須設(shè)置的依賴關(guān)系。
1.3.1 BeanFactory 接口
??? 因為?org.springframework.beans.factory.BeanFactory?是一個簡單接口,所以可以針對各種底層存儲方法實現(xiàn)。最常用的?BeanFactory?定義是?XmlBeanFactory,它根據(jù) XML 文件中的定義裝入 bean,如清單1所示。
??? 清單1.XmlBeanFactory
????BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));
????在XML文件中定義的Bean是被懶加載的,這意味在需要bean之前,bean本身不會被初始化。要從BeanFactory檢索bean,只需調(diào)用getBean()方法,傳入將要檢索的 bean 的名稱即可,如清單2所示。
??? 清單2.getBean()
????MyBean mybean = (MyBean) factory.getBean("mybean");
??? 每個 bean 的定義都可以是 POJO (用類名和 JavaBean 初始化屬性定義)或?FactoryBean。FactoryBean?接口為使用 Spring 框架構(gòu)建的應(yīng)用程序添加了一個間接的級別。
1.4 IOC示例
??? 理解控制反轉(zhuǎn)最簡單的方式就是看它的實際應(yīng)用。在對由三部分組成的?Spring 系列?的第 1 部分進行總結(jié)時,我使用了一個示例,演示了如何通過 Spring IOC容器注入應(yīng)用程序的依賴關(guān)系(而不是將它們構(gòu)建進來)。
??? 我用開啟在線信用帳戶的用例作為起點。對于該實現(xiàn),開啟信用帳戶要求用戶與以下服務(wù)進行交互:
· ? ? ? 信用級別評定服務(wù),查詢用戶的信用歷史信息。
· ? ? ?遠程信息鏈接服務(wù),插入客戶信息,將客戶信息與信用卡和銀行信息連接起來,以進行自動借記(如果需要的話)。
· ? ? 電子郵件服務(wù),向用戶發(fā)送有關(guān)信用卡狀態(tài)的電子郵件。
1.5 ?三個接口
??? 對于這個示例,我假設(shè)服務(wù)已經(jīng)存在,理想的情況是用松散耦合的方式把它們集成在一起。以下清單顯示了三個服務(wù)的應(yīng)用程序接口。
??? 清單3. CreditRatingInterface
public interface CreditRatingInterface {
???public boolean getUserCreditHistoryInformation(ICustomer iCustomer);
}
??? 清單 3 所示的信用級別評定接口提供了信用歷史信息。它需要一個包含客戶信息的?Customer?對象。該接口的實現(xiàn)是由?CreditRating?類提供的。
??? 清單4.CreditLinkingInterface
public interface CreditLinkingInterface {
????????public ?String getUrl();
????????public ?void setUrl(String url);
????????public ?void linkCreditBankAccount() throws Exception ;
}
????信用鏈接接口將信用歷史信息與銀行信息(如果需要的話)連接在一起,并插入用戶的信用卡信息。信用鏈接接口是一個遠程服務(wù),它的查詢是通過?getUrl()?方法進行的。URL 由 Spring 框架的 bean 配置機制設(shè)置,我稍后會討論它。該接口的實現(xiàn)是由?CreditLinking?類提供的。
??? 清單5.EmailInterface
public ?interface EmailInterface {
??????public ?void sendEmail(ICustomer iCustomer);
??????public ?String getFromEmail();
??????public ?void setFromEmail(String fromEmail) ;
??????public String getPassword();
??????public ?void setPassword(String password) ;
??????public ?String getSmtpHost() ;
??????public void setSmtpHost(String smtpHost);
??????public ?String getUserId() ;
??????public ?void setUserId(String userId);
???}
? ??EmailInterface?負責向客戶發(fā)送關(guān)于客戶信用卡狀態(tài)的電子郵件。郵件配置參數(shù)(例如 SMPT 主機、用戶名、口令)由前面提到的 bean 配置機制設(shè)置。Email?類提供了該接口的實現(xiàn)。
1.6 ?Spring 使其保持松散
??? 這些接口就位之后,接下來要考慮的就是如何用松散耦合方式將它們集成在一起。在?清單 6?中可以看到信用卡帳戶用例的實現(xiàn)。
??? 注意,所有的 setter 方法都是由 Spring 的配置 bean 實現(xiàn)的。所有的依賴關(guān)系(也就是三個接口)都可以由 Spring 框架用這些 bean 注入。createCreditCardAccount()?方法會用服務(wù)去執(zhí)行其余實現(xiàn)。在?清單 7?中可以看到 Spring 的配置文件。我用箭頭突出了這些定義。?
1.7 ? 運行應(yīng)用程序
??? 要運行示例應(yīng)用程序,首先必須?下載 Spring 框架?及其所有依賴文件。接下來,將框架釋放到(比如說)磁盤?c:\,這會創(chuàng)建?C:\spring-framework-1.2-rc2?(適用于當前發(fā)行版本) 這樣的文件夾。在繼續(xù)后面的操作之前,還必須下載和釋放?Apache Ant。
? ??接下來,將源代碼釋放到文件夾,例如?c:\?盤,然后創(chuàng)建?SpringProject。將 Spring 庫(即?C:\spring-framework-1.2-rc2\dist下的?spring.jar?和?C:\spring-framework-1.2-rc2\lib\jakarta-commons?下的??commons-logging.jar)復制到?SpringProject\lib?文件夾中。完成這些工作之后,就有了必需的構(gòu)建依賴關(guān)系集。
??? 打開命令提示符,將當前目錄切換到?SpringProject,在命令提示符中輸入以下命令:build。?
??? 這會構(gòu)建并運行?CreateCreditAccountClient?類,類的運行將創(chuàng)建?Customer?類對象并填充它,還會調(diào)用?CreateCreditCardAccount?類創(chuàng)建并鏈接信用卡帳戶。CreateCreditAccountClient?還會通過?ClassPathXmlApplicationContext?裝入 Spring 配置文件。裝入 bean 之后,就可以通過?getBean()?方法訪問它們了,如清單 8 所示。
??? 清單 8. 裝入 Spring 配置文件
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {
?????"springexample-creditaccount.xml"
?});
CreateCreditCardAccountInterface ?creditCardAccount = (CreateCreditCardAccountInterface)
????appContext.getBean("createCreditCard");
1.8 結(jié)束語
??? 在這篇由三部分組成的?Spring 系列?的第一篇文章中,我介紹了 Spring 框架的基礎(chǔ)。我從討論組成 Spring 分層架構(gòu)的 7 個模塊開始,然后深入介紹了其中兩個模塊:Spring AOP 和 IOC 容器。
??? 由于學習的最佳方法是實踐,所以我用一個工作示例介紹了 IOC 模式(像 Spring 的 IOC 容器實現(xiàn)的那樣)如何用松散耦合的方式將分散的系統(tǒng)集成在一起。在這個示例中可以看到,將依賴關(guān)系或服務(wù)注入工作中的信用卡帳戶應(yīng)用程序,要比從頭開始構(gòu)建它們?nèi)菀椎枚唷?/p>
??? 請繼續(xù)關(guān)注這一系列的下一篇文章,我將在這里學習的知識基礎(chǔ)上,介紹 Spring AOP模塊如何在企業(yè)應(yīng)用程序中提供持久支持,并讓您開始了解 Spring MVC 模塊和相關(guān)插件。
2 Spring AOP與Hibernate
2.1 ?Spring AOP
??? 軟件系統(tǒng)通常由多個組件構(gòu)成,每個組件負責一個特定的功能領(lǐng)域。但是,這些組件也經(jīng)常承擔它們的核心功能之外的額外責任。系統(tǒng)服務(wù)(例如日志、事務(wù)管理和安全性)經(jīng)常發(fā)現(xiàn)自己跑到了別的組件的領(lǐng)域里,而這些組件的核心職責是其他事情。結(jié)果就是所謂的“代碼糾纏”,或者更簡單點兒說“一團糟”。面向方面編程是一種試圖解決這個問題的編程技術(shù),它把關(guān)注點的隔離提升為核心的編程概念。
??? 使用 AOP 時,仍然是在一個地方定義系統(tǒng)的公共功能,但是可以聲明性地定義?如何?和?在哪里?應(yīng)用這個功能。如果對橫切關(guān)注點(例如日志和事務(wù)管理)進行了模塊化,那么不用修改每個單獨的類,就可以向代碼中添加新特性。這類模塊化的關(guān)注點稱作?方面。
??? 以一個企業(yè)應(yīng)用程序為例。這類應(yīng)用程序通常要求類似于安全性和事務(wù)支持的服務(wù)。顯然,可以把這些服務(wù)的支持直接編寫到要求服務(wù)的每個類當中,但是更希望能夠不必為大量事務(wù)性上下文編寫同樣的事務(wù)處理代碼。如果使用 Spring AOP進行事務(wù)處理,那么可以聲明性地安排適當?shù)姆椒ㄕ{(diào)用,而不必逐個安排。
??? Spring AOP提供了幾個方面,可以為 JavaBean 聲明事務(wù)。例如,TransactionProxyFactoryBean?是個方便的代理類,能夠攔截對現(xiàn)有類的方法調(diào)用,并把事務(wù)上下文應(yīng)用到事務(wù) bean。在下面的示例中會看到這個類的實際應(yīng)用。
2.2 ? Hibernate
??? Spring框架提供了對 Hibernate、JDO 和 iBATIS SQL
????Maps 的集成支持。Spring 對 Hibernate 的支持是第一級的,整合了許多 IOC 的方便特性,解決了許多典型的 Hibernate 集成問題??蚣軐?Hibernate 的支持符合 Spring 通用的事務(wù)和數(shù)據(jù)訪問對象(DAO)異常層次結(jié)構(gòu)。
??? Spring為使用選擇的 OR 映射層來創(chuàng)建數(shù)據(jù)訪問應(yīng)用程序提供了支持。因為所有東西都設(shè)計成一組可重用 JavaBean,所以不管選擇什么技術(shù),都能以庫的格式訪問大多數(shù) Spring 的 OR 映射支持。?ApplicationContext?或?BeanFactory?內(nèi)部的 OR 映射的好處是簡化了配置和部署。
??? Hibernate是 Java 平臺上一個功能全面的、開源的 OR 映射框架。Hibernate 支持開發(fā)符合常規(guī) Java 理念的持久性類 —— 包括關(guān)聯(lián)、繼承、多態(tài)、復合以及 Java 集合框架。Hibernate 查詢語言(HQL)被設(shè)計成 SQL 的一個微型面向?qū)ο髷U展,它是對象和關(guān)系世界之間的橋梁。Hibernate 也支持用原始 SQL 或基于 Java 的標準和示例查詢表達查詢。Hibernate 使用 XML(*.hbm.xml)文件把 Java 類映射到表,把 JavaBean 屬性映射到數(shù)據(jù)庫表。
??? 通過 JDBC 技術(shù),支持所有的 SQL 數(shù)據(jù)庫管理系統(tǒng)。Hibernate 與所有流行的 J2EE 應(yīng)用程序服務(wù)器和 Web 容器都很好地集成。
2.3 ? 實際示例
??? 一個銀行應(yīng)用程序示例可以讓您自己看到 Spring AOP和 Hibernate 一起工作有多么好。銀行帳戶用例允許用戶 (Customer)在一個事務(wù)中打開一個或多個銀行帳戶。用戶可以申請多個銀行帳戶,可以選擇是支票帳戶類型或者是儲蓄帳戶類型。
??? 應(yīng)用程序數(shù)據(jù)庫(Cloudscape?)容納所有客戶和帳戶信息。在這個例子中,假設(shè)在?Customer?和?Account?類之間存在?1:N?的關(guān)聯(lián)。在實際生活場景中,關(guān)聯(lián)可能需要按?m:n?建模,才能支持聯(lián)合帳戶。
??? 由于用戶必須可以在一個事務(wù)中申請多個帳戶,所以首先要為數(shù)據(jù)庫交互實現(xiàn)一個 DOA 模式。然后要設(shè)置 Spring AOP的?TransactionProxyFactoryBean,讓它攔截方法調(diào)用并聲明性地把事務(wù)上下文應(yīng)用到 DOA。
2.4 ? Hibernate實踐
??? 在Spring框架中,像JDBC?DataSource或Hibernate?SessionFactory這樣的資源,在應(yīng)用程序上下文中可以用bean實現(xiàn)。需要訪問資源的應(yīng)用程序?qū)ο笾恍柰ㄟ^bean引用得到這類預先定義好的實例的引用即可(這方面的更多內(nèi)容在?下一節(jié)中)。在清單1中,可以看到示例銀行應(yīng)用程序的一段摘錄:XML 應(yīng)用程序上下文定義顯示了如何設(shè)置JDBC?DataSource,并在上面放一個Hibernate?SessionFactory。
??? 清單1.JDBC DataSource 和 HibernateSessionFactory 連接


??? 清單 1?顯示了如何為示例應(yīng)用程序數(shù)據(jù)庫(是 Cloudscape)配置數(shù)據(jù)源 bean(exampleDataSource)。exampleDatasource被連接到 Spring Hibernate 的?SessionFactory。請注意?*.hbm.xml?指定了示例應(yīng)用程序的OR映射文件。?
??? 數(shù)據(jù)源和會話工廠設(shè)置好之后,下一步就是在DAO中連接,在?CustomerDAOImpl?示例中,要使用?SessionFactory。接下來,插入Spring的TransactionProxyFactoryBean,它會攔截對應(yīng)用程序的CustomerDAOImpl對象的方法調(diào)用,并聲明性地在它上面應(yīng)用事務(wù)。
??? 在?清單 2?的這個示例中,CustomerDAOImpl?類的addCustomer?方法是作為事務(wù)的一部分執(zhí)行的,有一個事務(wù)屬性?PROPAGATION_REQUIRED。這個屬性等價于 EJB 容器的?TX_REQUIRED。如果想讓這個方法一直在事務(wù)中運行,可以使用?PROPAGATION_REQUIRED。如果事務(wù)已經(jīng)在運行,那么 bean 方法會加入事務(wù),否則 Spring 的輕量級事務(wù)管理器會啟動一個事務(wù)。如果想在調(diào)用組件服務(wù)時總是啟動新事務(wù),可以使用?PROPAGATION_REQUIRES_NEW?屬性。
??? 應(yīng)用程序的連接完成之后,現(xiàn)在來進一步查看源代碼。
2.5 ? 分析這個!
??? 如果以前沒這么做過,那么請?下載這篇文章的源代碼。把源 zip 文件釋放到計算機中的任何位置上,例如?c:\。會創(chuàng)建一個叫作?SpringProjectPart2?的文件夾。src\spring?文件夾包含示例應(yīng)用程序的 Hibernate 映射文件和 Spring 配置文件。src\springexample\hibernate?文件包含應(yīng)用程序的源代碼。
??? 在這里會發(fā)現(xiàn)兩個類,即?Customer?和??Account,它們用 Hibernate 映射文件映射到兩個表。Customer?類代表客戶信息,Account?代表客戶的帳戶信息。正如前面提到的,我把這兩個類按照?1: N?關(guān)系進行建模,即一個?Customer?可以擁有多個?Account。清單3顯示了?Customer?對象的 Hibernate 映射文件。
??? 清單 3. Customer 對象的 Hibernate 映射文件


??? set name="accounts"?和一對多類標簽指定了?Customer?和?Account?之間的關(guān)系。我還在?Account.hbm.xml?文件中定義了?Account?對象的映射。
??? CustomerDAOImpl.java?代表應(yīng)用程序的 DAO,它在應(yīng)用程序數(shù)據(jù)庫中插入客戶和帳戶信息。CustomerDAOImpl?擴展了 Spring 的?HibernateDaoSupport,它用 Spring
????HibernateTemplate 簡化了會話管理。這樣,可以通過?getHibernateTemplate()?方法保存或檢索數(shù)據(jù)。下面顯示的?getCustomerAccountInfo()?對?Customer?進行?查找,通過getHibernateTemplate().find方法用 HQL 得到客戶的帳戶信息,如清單 4 所示。
??? 清單 4. DAO 實現(xiàn)
public ?class CustomerDAOImpl extends HibernateDaoSupport implements CustomerDAO{
??????public void addCustomer(Customer customer) {
????????????getHibernateTemplate().save(customer);????
????????????//TODO Auto-generated method stub
??????}
??????public Customer getCustomerAccountInfo(Customer customer) {
????????Customer cust = null;
????????List list = getHibernateTemplate().find("from Customer customer " +
??????????"where customer.userId = ?" , customer.getUserId(),Hibernate.STRING);
????????if(list.size() > 0){
??????????cust = (Customer)? list.get(0);
????????}
????????return ?cust;
??}
??? 所有這些都應(yīng)當很容易掌握?,F(xiàn)在來看代碼的實際應(yīng)用!
2.6 ?運行應(yīng)用程序
??? 要運行示例應(yīng)用程序,必須首先?下載 Spring 框架?和它的全部依賴文件。接下來,釋放框架到某一位置(比如?c:\?),這會創(chuàng)建文件夾?C:\spring-framework-1.2-rc2(針對當前發(fā)行版)。在繼續(xù)之前還必須下載和釋放?Apache Ant?和?Cloudscape。下載 Cloudscape之后,把它釋放到?c:\?,這會創(chuàng)建文件夾?C:\Cloudscape_10.0。
??? 接下來,釋放源代碼到?c:\?,這會創(chuàng)建?SpringProject2?文件夾。接下來修改?build.xml?文件的入口,用實際安裝 Spring 的位置代替?C:\spring-framework-1.2-rc2,用實際安裝 Cloudscape的位置代替?C:\Program?Files\IBM\Cloudscape_10.0。
??? 打開命令行提示符,進入?SpringProject?目錄,在命令行提示符下輸入以下命令:build.?
????這會構(gòu)建并運行?CreateBankCustomerClient?類,它會創(chuàng)建?Customer?類對象,用數(shù)據(jù)填充它,創(chuàng)建?Account?對象,填充它,并把它添加到?Customer?對象。
??? 然后?CreateBankCustomerClient?會調(diào)用?CustomerDAOImpl.addCustomer?類,添加客戶和帳戶信息。一旦插入完成,CreateBankCustomerClient?會調(diào)用CustomerDAOImpl.getCustomerAccountInfo?方法,根據(jù)?userid?得到客戶和帳戶信息。如果?CreateBankCustomerClient?執(zhí)行成功,會在控制臺上看到打印出?userid。也可以查詢 Cloudscape數(shù)據(jù)庫檢索客戶和帳戶信息。?
2.7 ?結(jié)束語
??? 在三部分的?Spring 系列?的第 2 部分中,我介紹了如何集成 Spring?Hibernate和Spring AOP。結(jié)果是一個強健的持久性框架,支持聲明性的實現(xiàn)事務(wù)。
??? 在這個系列的下一篇,也是最后一篇文章中,我將介紹 Spring 的 MVC 模塊,介紹如何用它來簡化基于 Web 的應(yīng)用程序的創(chuàng)建。
3 Spring MVC框架
3.1 Spring MVC框架
??? Spring框架提供了構(gòu)建 Web 應(yīng)用程序的全功能 MVC 模塊。使用 Spring 可插入的 MVC 架構(gòu),可以選擇是使用內(nèi)置的 Spring Web 框架還是 Struts 這樣的 Web 框架。通過策略接口,Spring 框架是高度可配置的,而且包含多種視圖技術(shù),例如 JavaServer Pages(JSP)技術(shù)、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道使用的視圖,所以不會強迫您只使用 JSP 技術(shù)。Spring MVC 分離了控制器、模型對象、分派器以及處理程序?qū)ο蟮慕巧?,這種分離讓它們更容易進行定制。
?? ?Spring的Web MVC框架是圍繞DispatcherServlet設(shè)計的,它把請求分派給處理程序,同時帶有可配置的處理程序映射、視圖解析、本地語言、主題解析以及上載文件支持。默認的處理程序是非常簡單的 Controller 接口,只有一個方法 ModelAndView handleRequest(request,response)。Spring 提供了一個控制器層次結(jié)構(gòu),可以派生子類。如果應(yīng)用程序需要處理用戶輸入表單,那么可以繼承AbstractFormController。如果需要把多頁輸入處理到一個表單,那么可以繼承AbstractWizardFormController。
??? 示例應(yīng)用程序有助于直觀地學習這些特性。銀行應(yīng)用程序允許用戶檢索他們的帳戶信息。在構(gòu)建銀行應(yīng)用程序的過程中,可以學到如何配置 Spring MVC 框架和實現(xiàn)框架的視圖層,視圖層包括 JSTL 標記(用于顯示輸出的數(shù)據(jù))和JavaServer Pages 技術(shù)。
3.2 配置Spring MVC
??? 要開始構(gòu)建示例應(yīng)用程序,請配置 Spring MVC 的 DispatcherServlet。請在 web.xml 文件中注冊所有配置。清單1顯示了如何配置 sampleBankingServlet。
??? 清單1. 配置Spring MVC DispatcherServlet

??? DispatcherServlet從一個XML文件裝入Spring應(yīng)用程序上下文,XML文件的名稱是servlet 的名稱后面加上-servlet 。在這個示例中,DispatcherServlet 會從 sampleBankingServlet-servlet.xml 文件裝入應(yīng)用程序上下文。
3.3 配置應(yīng)用程序的URL
??? 下一步是配置想讓sampleBankingServlet處理的URL。同樣,還是要在web.xml中注冊所有這些信息。
??? 清單 2. 配置想要處理的URL

3.4 裝入配置文件
??? 下面,裝入配置文件。為了做到這點,請為 Servlet 2.3 規(guī)范注冊 ContextLoaderListener 或為 Servlet 2.2 及以下的容器注冊 ContextLoaderServlet。為了保障后向兼容性,請用ContextLoaderServlet。在啟動 Web 應(yīng)用程序時,ContextLoaderServlet 會裝入 Spring 配置文件。清單3注冊了 ContextLoaderServlet。
??? 清單 3. 注冊 ContextLoaderServlet

??? contextConfigLocation參數(shù)定義了要裝入的 Spring 配置文件,如下面的 servlet 上下文所示。

??? sampleBanking-services.xml 文件代表示例銀行應(yīng)用程序服務(wù)的配置和 bean 配置。如果想裝入多個配置文件,可以在 標記中用逗號作分隔符。
3.5 Spring MVC示例
??? 示例銀行應(yīng)用程序允許用戶根據(jù)惟一的 ID 和口令查看帳戶信息。雖然 Spring MVC 提供了其他選項,但是我將采用 JSP 技術(shù)作為視圖頁面。這個簡單的應(yīng)用程序包含一個視圖頁用于用戶輸入(ID 和口令),另一頁顯示用戶的帳戶信息。
??? 我從 LoginBankController 開始,它擴展了 Spring MVC 的 SimpleFormController。SimpleFormContoller 提供了顯示從 HTTP GET 請求接收到的表單的功能,以及處理從 HTTP POST 接收到的相同表單數(shù)據(jù)的功能。LoginBankController 用 AuthenticationService 和 AccountServices 服務(wù)進行驗證,并執(zhí)行帳戶活動?!?配置視圖屬性 ”一節(jié)中的 清單 5 描述了如何把 AuthenticationService 和 AccountServices 連接到 LoginBankController。 清單 4顯示了 LoginBankController 的代碼。
3.6 配置視圖屬性
??? 下面,我必須注冊在接收到 HTTP GET 請求時顯示的頁面。我在 Spring 配置中用 formView 屬性注冊這個頁面,如清單 5 所示。sucessView 屬性代表表單數(shù)據(jù)提交而且 doSubmitAction() 方法中的邏輯成功執(zhí)行之后顯示的頁面。formView 和 sucessView 屬性都代表被定義的視圖的邏輯名稱,邏輯名稱映射到實際的視圖頁面。
??? 清單 5. 注冊 LoginBankController

??? commandClass和 commandName 標記決定將在視圖頁面中活動的 bean。例如,可以通過 login.jsp 頁面訪問 loginCommand bean,這個頁面是應(yīng)用程序的登錄頁面。一旦用戶提交了登錄頁面,應(yīng)用程序就可以從 LoginBankController 的 onSubmit() 方法中的命令對象檢索出表單數(shù)據(jù)。
3.7 視圖解析器
??? Spring MVC的 視圖解析器 把每個邏輯名稱解析成實際的資源,即包含帳戶信息的 JSP 文件。我用的是 Spring 的 InternalResourceViewResolver,如 清單 6所示。
??? 因為我在 JSP 頁面中使用了 JSTL 標記,所以用戶的登錄名稱解析成資源 /jsp/login.jsp,而 viewClass 成為 JstlView。
3.8 驗證和帳戶服務(wù)
??? 就像前面提到的,LoginBankController 內(nèi)部連接了 Spring 的 AccountServices 和 AuthenticationService。AuthenticationService 類處理銀行應(yīng)用程序的驗證。AccountServices 類處理典型的銀行服務(wù),例如查找交易和電匯。清單 7 顯示了銀行應(yīng)用程序的驗證和帳戶服務(wù)的配置。
??? 清單 7. 配置驗證和帳戶服務(wù)

????以上服務(wù)在 sampleBanking-services.xml 中注冊,然后裝入 web.xml 文件中,就像 前面討論的那樣??刂破骱头?wù)配置好后,這個簡單的應(yīng)用程序就完成了。現(xiàn)在我們來看看部署和測試它時會發(fā)生什么!
3.9 部署應(yīng)用程序
??? 我把示例應(yīng)用程序部署在 Tomcat servlet 容器中。Tomcat 是 Java Servlet 和 Java ServerPagest 技術(shù)的官方參考實現(xiàn)中使用的 servlet 容器。如果以前沒這么做過,請 下載 jakarta-tomcat-5.0.28.exe并運行它把 Tomcat 安裝到自己喜歡的任何位置,例如 c:\tomcat5.0。
??? 接下來,下載示例代碼 并釋放到驅(qū)動器(例如 c:\ )上。創(chuàng)建了 Spring 項目的文件夾之后,打開它并把 spring-banking 子文件夾拷貝到 c:\tomvat5.0\webapps。spring-banking 文件夾是一個 Web 檔案,里面包含 Spring MVC 示例應(yīng)用程序。lib 文件夾包含應(yīng)用程序需要的 Spring 框架、與Spring 相關(guān)的 MVC 庫以及 JSTL 標記庫和 jar 文件。
????要啟動 Tomcat 服務(wù)器,請使用以下命令:
??? cd bin C:\Tomcat 5.0\bin>catalina.bat start
??? Tomcat應(yīng)當啟動并部署 Spring MVC 示例應(yīng)用程序。
3.10 ?測試應(yīng)用程序
??? 要測試應(yīng)用程序,請打開 Web 瀏覽器,指向http://localhost:tomcatport/springbanking并用 Tomcat 服務(wù)器實際運行的端口替換 tomcatport。應(yīng)當看到圖 1 所示的登錄屏幕。輸入用戶 ID “admin”和口令“password”,并按下登錄按鈕。其他用戶 ID 或口令會造成來自驗證服務(wù)的錯誤。
??? 圖 1. Spring MVC 示例登錄屏幕

登錄成功之后,會看到圖 2 所示的帳戶細節(jié)頁面。
圖 2. Spring MVC 示例帳戶細節(jié)頁面

3.11 ?結(jié)束語
??? 在三部分的 Spring 系列的第三篇文章中,我介紹了 Spring MVC 框架的特性。我演示了如何配置和開發(fā) Spring MVC 應(yīng)用程序、如何配置 Spring MVC 控制器和向其中插入依賴項、如何用 JavaServer Pages 技術(shù)開發(fā)應(yīng)用程序視圖,以及如何把自己的頁面與 Spring MVC 的視圖層集成??偨Y(jié)這篇文章時,我演示了如何在 Tomcat servlet 容器中部署應(yīng)用程序以及如何在瀏覽器中測試它。
??? 請繼續(xù)關(guān)注 Spring 系列 的下一篇文章。在下一篇文章中,我將介紹如何把基于 JMS 的應(yīng)用程序與 Spring 框架集成。同時,請參閱 參考資料 學習更多有關(guān) Spring 框架和 Spring MVC 的內(nèi)容。
4 ?參考鏈接
Spring框架簡介
https://www.ibm.com/developerworks/cn/java/wa-spring1/
當Hibernate遇上Spring
https://www.ibm.com/developerworks/cn/java/wa-spring2/index.html?ca=drs-