http://blog.csdn.net/slnqnd/article/details/1772910/html
Struts2.0 +Hibernate 3.2 +Spring 2.0java
一. Struts程序員
1.定義web
它是使用 servlet 和 JavaServer Pages 技術的一種 Model-View-Controller 實現, 可幫助您控制Web 項目中的變化並提升專業化水平。「模型-視圖-控制 器」(MVC) 就是用來幫助您控制變化的一種設計模式。MVC 減弱了業務邏輯接口和數據接口之間的耦合。Struts 是一種 MVC 實現,它將 Servlet 2.2 和 JSP 1.1 標記(屬於 J2EE 規範)用做實現的一部分。(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)spring
2.結構sql
在 struts+hibernate+spring 三層結構模型中處於表現層數據庫
Struts框架的組件結構圖apache
(http://www-128.ibm.com/developerworks/cn/java/l-struts-mvc/index.html)編程
3.業務流程及核心原理設計模式
Struts 對MVC框架提供了對開發MVC系統的底層支持,它採用的主要技術是Servlet,JSP和custom tag library。
(http://www-128.ibm.com/developerworks/cn/java/l-struts-mvc/index.html)
Struts uml 圖
做爲一個MVC的框架,Struts對Model、View和Controller都提供了對應的實現組件,對應上面的UML圖,分別進行介紹,而且看看它們是如何結合在一塊兒的。
2. Model: 模型包含應用程序的核心功能。模型封裝了應用程序的狀態。有時它包含的惟一功能就是狀態。它對視圖 或控制器一無所知。MVC系統中的Model部分從概念上能夠分爲兩類--系統的內部狀態,和改變系統狀態的動做。Struts爲Model部分提供了 Action和ActionForm對象:全部的Action處理器對象都是開發者從Struts的Action類派生的子類。Action處理器對象封 裝了具體的處理邏輯,調用業務邏輯模塊,而且把響應提交到合適的View組件以產生響應。Struts提供的ActionForm組件對象,它能夠經過定 義屬性描述客戶端表單數據。開發者能夠從它派生子類對象,利用它和Struts提供的自定義標記庫結合能夠實現對客戶端的表單數據的良好封裝和支 持,Action處理器對象能夠直接對它進行讀寫,而再也不須要和request、response對象進行數據交互。經過ActionForm組件對象實 現了對View和Model之間交互的支持。Struts一般建議使用一組JavaBean表示系統的內部狀態,根據系統的複雜度也可使用像 Entity EJB 和 Session EJB等組件來實現系統狀態。Struts建議在實現時把"作什麼"(Action)和"如何作"(業務邏輯)分離。這樣能夠實現業務邏輯的重用。
3.View:視圖提供模型的表示。它是應用程序的 外觀。視圖能夠訪問模型的讀方法,但不能訪問寫 方法。此外,它對控制器一無所知。當更改模型時,視圖應獲得通知。 Struts應用中的View部分是經過JSP技術實現的。Struts提供了自定義 的標記庫可使用,經過這些自定義標記能夠很是好地和系統的Model部分交互,經過使用這些自定義標記建立的JSP表單,能夠實現和Model部分中的 ActionForm的映射,完成對用戶數據的封裝,同時這些自定義標記還提供了像模板定製等多種顯示功能。
Struts框架的處理流程清楚的體現了MVC系統的特色,簡單的Struts組件結構。Struts Controller ActionServlet處理客戶請求,利用配置的ActionMapping對象把請求映射到Action處理器對象進行處理。Action處理對象 訪問ActionForm中的數據,處理和響應客戶請求,它還調用後臺的Bean組件,這些組件封裝了具體的業務邏輯。Action處理器對象根據處理結 果通知Controller,Controller進行下一步的處理。
總結一下各種:
(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
Command (ActionServlet) 與 Model (Action & ActionForm) 之間的關係的 UML 圖
ActionServlet 類
Struts 的控制器是將事件(事件一般是 HTTP post)映射到類的一個 servlet。控制器使用配置文件以使您沒必要對這些值進行硬編碼。ActionServlet 是該 MVC 實現 的 Command 部分,它是這一框架的核心。 ActionServlet (Command) 建立並使 用 Action 、 ActionForm 和ActionForward 。如前所述, struts-config.xml 文件配置 該 Command。在建立 Web 項目時,您將擴展 Action 和 ActionForm 來解決特定的問題。文件 struts- config.xml 指示ActionServlet 如何使用這些擴展的類。這種方法有幾個優勢:
能夠經過擴展 ActionServlet 來添加 Command 功能。
ActionForm 類
ActionForm 維護 Web 應用程序的會話狀態。 ActionForm 是一個抽象類,必須爲每一個輸入表單模型建立該類的子類。當我說 輸入表單模型 時,是指 ActionForm 表示的是由 HTML 表單設置或更新的通常意義上的數據。例如,您可能有一個由 HTML 表單設置的 UserActionForm。Struts 框架將執行如下操做:
注:
Action 類
Action 類是業務邏輯的一個包裝。 Action 類的用途是將 HttpServletRequest 轉換爲業務邏輯。要使用 Action ,請建立它的子類並覆蓋 process() 方法。
ActionServlet (Command) 使用 perform() 方法將參數化的類傳遞 給 ActionForm 。仍然沒有太多討厭的 request.getParameter() 調用。當事件進展到這一步時,輸入表單數據(或 HTML 表單數據)已被從請求流中提取出來並轉移到 ActionForm 類中。
注:擴展 Action 類時請注意簡潔。 Action 類應該控制應用程序的流程,而不該該控制應用程序的邏輯。經過將業務邏輯放在單獨的包或 EJB 中,咱們就能夠提供更大的靈活性和可重用性。
考慮 Action 類的另外一種方式是 Adapter 設計模式。 Action 的用途是「將類的接口轉換爲客戶機 所需的另外一個接口。Adapter 使類可以協同工做,若是沒有 Adapter,則這些類會由於不兼容的接口而沒法協同工做。」(摘自 Gof 所著 的 Design Patterns - Elements of Reusable OO Software)。本例中的客戶機 是 ActionServlet ,它對咱們的具體業務類接口一無所知。所以,Struts 提供了它可以理解的一個業務接口,即 Action 。經過 擴展 Action ,咱們使得咱們的業務接口與Struts 業務接口保持兼容。(一個有趣的發現是, Action 是類而不是接 口)。 Action 開始爲一個接口,後來卻變成了一個類。真是金無足赤。)
Error 類
UML 圖(圖 6)還包括 ActionError 和 ActionErrors 。 ActionError 封 裝了單個錯誤消息。 ActionErrors 是 ActionError 類的容器,View 可使用標記訪問這些類。 ActionError 是 Struts 保持錯誤列表的方式。
圖 7. Command (ActionServlet) 與 Model (Action) 之間的關係的 UML 圖
ActionMapping 類
輸入事件一般是在 HTTP 請求表單中發生的,servlet 容器將 HTTP 請求轉換爲 HttpServletRequest 。控制器查看輸入事件並將請求分派給某個 Action 類。 struts-config.xml 確 定 Controller 調用哪一個 Action 類。 struts-config.xml 配置信息被轉換爲一組 ActionMapping , 然後者又被放入 ActionMappings 容器中。(您可能還沒有注意到這一點,以 s結尾的類就是容器)
ActionMapping 包含有關特定事件如何映射到特定 Action 的信 息。 ActionServlet(Command) 經過 perform() 方法將 ActionMapping 傳遞給 Action 類。這樣 就使 Action可訪問用於控制流程的信息。
ActionMappings
ActionMappings 是 ActionMapping 對象的一個集合。
4.利用Struts框架開發MVC系統要作的工做
(http://www-128.ibm.com/developerworks/cn/java/l-struts-mvc/index.html)
因爲Struts已經爲咱們提供了一個很是好的MVC框架,咱們利用Struts開發MVC系統時能夠大大加快開發的速度。在開發時能夠採用的一個開發流程以下:
具體在使用Struts框架時,對應各個部分的開發工做主要包括:
下面對這兩個配置文件作一些介紹:
web.xml文件的配置:
web應用中的web.xml是第一個要配置的地方,它描述了系統的Controller對象。在web.xml中增長以下標記
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>application</param-name> ?????? </servlet> |
說明:這個servlet對象就是Struts提供的Controller,還能夠爲它指定初始化參數,好比對系統應用屬性的支持。
<servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servelt-mapping> |
說明:實現客戶請求的url信息和服務器端具體處理的映射關係。
<taglib> <taglib-url>/WEB-INF/struts-bean.tld</taglib-url> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> ??????? |
說明:添加對Struts提供的應用所使用的自定義標記庫的引用。
struts-config.xml文件的配置:
struts-config.xml是用於創建Controller和Model之間的關係的。它描述了Controller所使用的把請求對應到具體處理的法則,同時它還描述了客戶提供的數據與ActionForm組件的對應映射關係。
在struts-config.xml中增長以下標記
<form-beans> <form-bean name="loginForm" type="loginForm" /> </form-beans> |
說明:<form-bean>標記描述一個具體的ActionForm子類對象,經過它和JSP頁面中的自定標記的結合使用能夠實現ActionForm和View之間的數據映射。
<action-mappings> <action path="/login" type="loginAction" name="loginForm" input="/login.jsp" ??? /> </action-mappings> |
說明:<action-mappings>標記描述了請求和處理的一對一映射關係。input和path屬 性惟一的標記了客戶端的一個請求,name屬性描述封裝客戶端的數據的ActionForm子類對象。Type屬性描述處理這個請求的Action子類對 象。
經過對兩個配置文件的配置,把Struts框架中MVC的各個部分聯繫起來,實現一個真正的MVC系統。
5. Struts 的優勢(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
l JSP 標記機制的使用
標記特性從 JSP 文件得到可重用代碼和抽象 Java 代碼。這個特性能很好地集成到基於 JSP的開發工具中,這些工具容許用標記編寫代碼。
l 標記庫
爲何要另發明一種輪子,或標記庫呢?若是您在庫中找不到您所要的標記,那就本身定義吧。此外,若是您正在學習 JSP 標記技術,則 Struts 爲您提供了一個起點。
l 開放源碼
您能夠得到開放源碼的所有優勢,好比能夠查看代碼並讓使用庫的每一個人檢查代碼。許多人均可以進行很好的代碼檢查。
l MVC 實現樣例
若是您但願建立您本身的 MVC 實現,則 Struts 可增長您的見識。
l 管理問題空間
分治是解決問題並使問題可管理的極好方法。固然,這是一把雙刃劍。問題愈來愈複雜,而且須要愈來愈多的管理。
6.Struts的缺點(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
二. Hibernate
1.定義
Hibernate是一個開放源代碼的對象關係映射框架,它對JDBC進行了很是輕量級的對象封裝,使得Java程序員能夠爲所欲爲的使用對象編程思惟來操縱數據庫。 Hibernate能夠應用在任何使用JDBC的場合,既能夠在Java的客戶端程序實用,也能夠在Servlet/JSP的Web應用中使用,最具革命意義的是,Hibernate能夠在應用EJB的J2EE架構中取代CMP, 完成數據持久化的重任。Hibernate 框架就容許Java中的對象-關係的持久性和查詢服務。Hibernate 對已經熟悉了SQL 和JDBC API的Java開發者來或具備中度的學習曲線。Hibernate 的持久對象基於POJO和Java 羣集(collections)。
2.Hibernate的體系結構及工做原理
(http://blog.csdn.net/hina1115/archive/2005/10/18/508717.aspx)
1.Hibernate 的初始化.
讀取Hibernate 的配置信息-〉建立Session Factory
1)建立Configeration類的實例。
它的構造方法:將配置信息(Hibernate config.xml)讀入到內存。
一個Configeration 實例表明Hibernate 全部Java類到Sql數據庫映射的集合。
2)建立SessionFactory實例
把Configeration 對象中的全部配置信息拷貝到SessionFactory的緩存中。
SessionFactory的實例表明一個數據庫存儲員源,建立後再也不與Configeration 對象關聯。
緩存(cache):指Java對象的屬性(一般是一些集合類型的屬性--佔用內存空間。
SessionFactory的緩存中:Hibernate 配置信息。O/R映射元數據。
緩存-大:重量級對象 小:輕量級對象
3)調用SessionFactory建立Session的方法
a.用戶自行提供JDBC鏈接。
Connection con=dataSource.getConnection();
Session s=sessionFactory.openSession(con);
b.讓SessionFactory提供鏈接
Session s=sessionFactory.openSession();
4)經過Session 接口提供的各類方法來操縱數據庫訪問。
3.Hibernate 的緩存體系
一級緩存:
Session 有一個內置的緩存,其中存放了被當前工做單元加載的對象。
每一個Session 都有本身獨立的緩存,且只能被當前工做單元訪問。
二級緩存:
SessionFactory的外置的可插拔的緩存插件。其中的數據可被多個Session共享訪問。
SessionFactory的內置緩存:存放了映射元數據,預約義的Sql語句。
4. Hibernate 中Java對象的狀態
1.臨時狀態 (transient)
特徵:
a.不處於Session 緩存中
b.數據庫中沒有對象記錄
Java如何進入臨時狀態
a.經過new語句剛建立一個對象時
b.當調用Session 的delete()方法,從Session 緩存中刪除一個對象時。
2.持久化狀態(persisted)
特徵:
a.處於Session 緩存中
b.持久化對象數據庫中設有對象記錄
c.Session 在特定時刻會保持兩者同步
Java如何進入持久化狀態
a.Session 的save()把臨時-》持久化狀態
b.Session 的load(),get()方法返回的對象
c.Session 的find()返回的list集合中存放的對象
d.Session 的update(),saveOrupdate()使遊離-》持久化
3.遊離狀態(detached)
特徵:
a.再也不位於Session 緩存中
b.遊離對象由持久化狀態轉變而來,數據庫中可能還有對應記錄。
Java如何進入持久化狀態-》遊離狀態
a.Session 的close()方法
b.Session 的evict()方法,從緩存中刪除一個對象。提升性能。少用。
5. Hibernate的優勢
(http://www.ibm.com/developerworks/cn/opensource/os-lightweight6/)
Hibernate 有一個靈活的映射機制。一些場景比其餘場景付出更多的努力來映射,可是若是您能在一個關係模式中表 示它,那麼也許在 Hibernate 中有一種方法來映射到它。Hibernate 的性能比大多數的框架要好並且還在不斷提高。文檔很優秀,收 購 JBoss 後,支持也在改善。JBoss 小組也把Hibernate 放置在一個合適的位置以搶在競爭者以前實現 JSR 200 持久性標準。
對 Hibernate 來講,與其餘開放源碼框架和商業框架的集成比其餘的替代框架要好。通常來講,Spring 與 Hibernate 的集成比與其餘任何一個持久性框架的集成要好。
Hibernate 是一個創新的框架。在推進與 SQL 的集成上,它比大多數其餘的框架走的更遠。它具備一些其餘框架不支持的特性,好比會話過濾。還有一支強大的公共和商業開發人員團隊爲其工做。
6. Hibernate的缺點
因爲其靈活性,相同的問題能夠有多種解決方案,沒法決定選擇何種方案。
Hibernate 比替代框架更加難以管理。
最後,Hibernate 不像一些持久性框架那麼專業。例如,對於一些邊緣狀況,好比管理懶散加載,Kodo JDO 有很是好的錯誤信息和更加可預測的行爲。
三.Spring
1. 定義
Spring是輕量級的J2EE應用程序框架。Spring的核心是個輕量級容器(container),實現了IoC(Inversion of Control)模式的容器,Spring的目標是實現一個全方位的整合框架,在Spring框架下實現多個子框架的組合,這些子框架之間彼此能夠獨立, 也可使用其它的框架方案加以替代,Spring但願提供one-stop shop的框架整合方案 。Spring的核心是個輕量級容器(container),實現了IoC(Inversion of Control)模式的容器,Spring的目標是實現一個全方位的整合框架,在Spring框架下實現多個子框架的組合,這些子框架之間彼此能夠獨立, 也可使用其它的框架方案加以替代,Spring但願提供one-stop shop的框架整合方案 。
2. Spring框架
(http://www.ibm.com/developerworks/cn/java/wa-spring1/)
Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在覈心容器之上,核心容器定義了建立、配置和管理 bean 的方式,如圖 1 所示。
圖 1. Spring 框架的 7 個模塊
組成 Spring 框架的每一個模塊(或組件)均可以單獨存在,或者與其餘一個或多個模塊聯合實現。每一個模塊的功能以下:
Spring 框架的功能能夠用在任何 J2EE 服務器中,大多數功能也適用於不受管理的環境。Spring 的核心 要點是:支持不綁定到特定 J2EE 服務的可重用業務和數據訪問對象。毫無疑問,這樣的對象能夠在不一樣 J2EE 環境 (Web 或 EJB)、獨立 應用程序、測試環境之間重用。
3. Spring的核心:IOC + AOP
(http://www.ibm.com/developerworks/cn/java/wa-spring1/)
a. IOC
控制反轉模式(也稱做依賴性介入)的基本概念是:不建立對象,可是描述建立它們的方式。在代碼中不直接與對象和服務鏈接,但在配置文件中描述哪個組件須要哪一項服務。容器 (在 Spring框架中是 IOC 容器) 負責將這些聯繫在一塊兒。
在典型的 IOC 場景中,容器建立了全部對象,並設置必要的屬性將它們鏈接在一塊兒,決定什麼時間調用方法。下表列出了 IOC 的一個實現模式。
類型1 |
服務須要實現專門的接口,經過接口,由對象提供這些服務,能夠從對象查詢依賴性(例如,須要的附加服務) |
類型2 |
經過 JavaBean 的屬性(例如 setter 方法)分配依賴性 |
類型3 |
依賴性以構造函數的形式提供,不以 JavaBean 屬性的形式公開 |
Spring 框架的 IOC 容器採用類型 2 和類型3 實現。
b. AOP
面向方面的編程,即 AOP,是一種編程技術,它容許程序員對橫切關注點或橫切典型的職責分界線的行爲(例如日誌和事務管理)進行模塊化。AOP 的核心構造是方面,它將那些影響多個類的行爲封裝到可重用的模塊中。
AOP 和 IOC 是補充性的技術,它們都運用模塊化方式解決企業應用程序開發中的複雜問題。在典型的面向對象開發方式中,可能要將日誌記錄語句放在全部方法和 Java 類中才能實現日誌功能。在 AOP 方式中,能夠反過來將日誌服務模塊化,並以聲明的方式將它們應用到須要日誌的組件上。固然,優點就是 Java 類不須要知道日誌服務的存在,也不須要考慮相關的代碼。因此,用Spring AOP 編寫的應用程序代碼是鬆散耦合的。
AOP 的功能徹底集成到了 Spring 事務管理、日誌和其餘各類特性的上下文中。
Spring 設計的核心是 org.springframework.beans
包,它的設計目標是與 JavaBean 組件一塊兒使用。這個包一般不是由用戶直接使用,而是由服務器將其用做其餘多數功能的底層中介。下一個最高級抽象是 BeanFactory
接口,它是工廠設計模式的實現,容許經過名稱建立和檢索對象。BeanFactory
也能夠管理對象之間的關係。
4. Spring的優勢
(http://www.imtinewlife.com/BBS/ShowPost.asp?ThreadID=201)
Spring能有效地組織你的中間層對象,不管你是否選擇使用了EJB。若是你僅僅使用了Struts或其餘的包含了J2EE特有APIs的framework,你會發現Spring關注了遺留下的問題。
. Spring能消除在許多工程上對Singleton的過多使用。根據個人經驗,這是一個主要的問題,它減小了系統的可測試性和麪向對象特性。
Spring 能消除使用各類各樣格式的屬性定製文件的須要,在整個應用和工程中,可經過一種一致的方法來進行配置。曾經感到迷惑,一個特定類要查找 迷幻般的屬性關鍵字或系統屬性,爲此不得不讀Javadoc乃至源編碼嗎?有了Spring,你可很簡單地看到類的JavaBean屬性。倒置控制的使用 (在下面討論)幫助完成這種簡化。 Spring能經過接口而不是類促進好的編程習慣,減小編程代價到幾乎爲零。
. Spring被設計爲讓使用它建立的應用盡量少的依賴於他的APIs。在Spring應用中的大多數業務對象沒有依賴於Spring。
. 使用Spring構建的應用程序易於單元測試。
. Spring能使EJB的使用成爲一個實現選擇,而不是應用架構的必然選擇。你能選擇用POJOs或localEJBs來實現業務接口,卻不會影響調用代碼。
. Spring幫助你解決許多問題而無需使用EJB。Spring能提供一種EJB的替換物,它們適於許多web應用。例如,Spring能使用AOP提供聲明性事務而不經過使用EJB容器,若是你僅僅須要與單個的數據庫打交道,甚至不須要JTA實現。
. Spring爲數據存取提供了一致的框架,不管是使用JDBC或O/Rmapping產品(如Hibernate)。
Spring確實使你能經過最簡單可行的解決辦法解決你的問題。這些特性是有很大價值的。
5. 總結
Spring的核心便是個IoC/DI的容器,它能夠幫程序設計人員完成組件之間的依賴關係注入,使得組件之間的依賴達到最小,進而提升組件的重用 性,Spring是個低侵入性(invasive)的框架,Spring中的組件並不會意識到它正置身於Spring中,這使得組件能夠輕易的從框架中脫 離,而幾乎不用任何的修改,反過來講,組件也能夠簡單的方式加入至框架中,使得組件甚至框架的整合變得容易。
Spring最爲人重視的另 一方面是支持AOP(Aspect-Oriented Programming),然而AOP框架只是Spring支持的一個子框架,說Spring框架是AOP框架並非一件適當的描述,人們對於新奇 的 AOP關注映射至Spring上,使得人們對於Spring的關注集中在它的AOP框架上,雖然有所誤解,但也突顯了Spring的另外一個使人關注的 特點。
Spring也提供MVC Web框架的解決方案,但您也能夠將本身所熟悉的MVC Web框架與Spring解合,像是Struts、Webwork等等,均可以與Spring整合而成爲進用於本身的解決方案。Spring也提供其它方 面的整合,像是持久層的整合如JDBC、O/R Mapping工具(Hibernate、iBATIS)、事務處理等等,Spring做了對多方面整合的努力,故說Spring是個全方位的應用程序框 架。
四.Struts + Hibernate + Spring的綜合應用
Struts: 用來做VC部分,即控制和顯示做用;
Spring: 用來做數據庫操做的事務處理,在配置文件裏配置好就OK了;
Hibernate:用來做DAO處理,在此用了Spring的getHibernateTemplate()方法來操做hsql進行數據增刪改等操做。
l 項目中 Sttuts、Hibernate、Spring的基本流程
1. Write your business class:
DTO, FormBean, Action, Service Interface, Service Implementation
2. Write JSP Pages
3. struts-config.xml Configuration : FormBean , Action , Forward pages.
4. applicationContext-service.xml Configuration : add your Service Interface and Service Implementation
5. Add your service factory Get method to ServiceFactory.java
6. Build project and Generate the Description file (*.hbm.xml) of DTO
7. applicationContext.xml Configuation : add *.hbm.xml file to applicationContext for O/R
Mapping.
l 用 Struts+Spring+Hibernate組裝WEB應用
(http://java.chinaitlab.com/Struts/39925.html)
表現層咱們將使用Struts;業務層咱們將使用Spring;持久層使用Hibrenate.
圖1展現了當這些框架組合在一塊兒時從高層看是什麼樣子。
圖1用Struts, Spring, 和 Hibernate框架構建的概覽
應用程序的分層
大多數不復雜的web應 用都能被分紅至少4個各負其責的層次。這些層次是:表現層、持久層、業務層、領域模型層。每層在應用程序中都有明確的責任,不該該和其它層混淆功能。每一 應用層應該彼此獨立但要給他們之間放一個通信接口。讓咱們從審視各個層開始,討論這些層應該提供什麼和不該該提供什麼。
表現層
在一個典型的web應用的一端是表現層。不少Java開發者也理解Struts所提供的。然而,太常見的是,他們把像業務邏輯之類的耦合的代碼放進了一個org.apache.struts.Action。因此,讓咱們在像Struts這樣一個框架應該提供什麼上取得一致意見。這兒是Struts負責的:
爲用戶管理請求和響應;
提供一個控制器代理調用業務邏輯和其它上層處理;
處理從其它層擲出給一個Struts Action的異常;
爲顯示提供一個模型;
執行用戶接口驗證。
這兒是一些常常用Struts編寫的可是卻不該該和Struts表現層相伴的項目:
直接和數據庫通信,好比JDBC調用;
業務邏輯和與你的應用程序相關的驗證;
事務管理;
在表現層中引入這種代碼將致使典型耦合和討厭的維護。
持久層
在典型web應用的另外一端是持久層。這一般是使事情迅速失控的地方。開發者低估了構建他們本身的持久層框架的挑戰性。通常來講,機構內部本身寫的持久層不只須要大量的開發時間,並且還常常缺乏功能和變得難以控制。有幾個開源的「對象-關係映射」框架很是解決問題。尤爲是,Hibernate框架爲java提供了"對象-關係持久化"機制和查詢服務。Hibernate對那些已經熟悉了SQL和JDBC API的Java開發者有一個適中的學習曲線。Hibernate持久對象是基於簡單舊式Java對象和Java集合。此外,使用Hibernate並不妨礙你正在使用的IDE。下面的列表包含了你該寫在一個持久層框架裏的代碼類型:
查詢相關的信息成爲對象。Hibernate經過一種叫做HQL的面向對象的查詢語言或者使用條件表達式API來作這個事情。 HQL很是相似於SQL-- 只是把SQL裏的table和columns用Object和它的fields代替。有一些新的專用的HQL語言成分要學;不過,它們容易理解並且文檔作得好。HQL是一種使用來查詢對象的天然語言,花很小的代價就能學習它。
保存、更新、刪除儲存在數據庫中的信息。
像Hibernate這樣的高級「對象-關係」映射框架提供對大多數主流SQL數據庫的支持,它們支持「父/子」關係、事務處理、繼承和多態。
這兒是一些應該在持久層裏被避免的項目:
業務邏輯應該在你的應用的一個高一些的層次裏。持久層裏僅僅容許數據存取操做。
你不該該把持久層邏輯和你的表現層邏輯攪在一塊兒。避免像JSPs或基於servlet的類這些表現層組件裏的邏輯和數據存取直接通信。經過把持久層邏輯隔離進它本身的層,應用程序變得易於修改而不會影響在其它層的代碼。例如:Hebernate可以被其它持久層框架或者API代替而不會修改在其它任何層的代碼。
業務層
在一個典型的web應 用程序的中間的組件是業務層或服務層。從編碼的視角來看,這個服務層是最容易被忽視的一層。不難在用戶接口層或者持久層裏找到散佈在其中的這種類型的代 碼。這不是正確的地方,由於這致使了應用程序的緊耦合,這樣一來,隨着時間推移代碼將很難維護。幸虧,針對這一問題有好幾種Frameworks存在。在這個領域兩個最流行的框架是Spring和PicoContainer,它們叫做微容器,你能夠不費力不費神的把你的對象連在一塊兒。全部這些框架都工做在一個簡單的叫做「依賴注入」(也通稱「控制反轉」)的概念上。這篇文章將着眼於Spring的爲指定的配置參數經過bean屬性的setter注入的使用。Spring也提供了一個構建器注入的複雜形式做爲setter注入的一個替代。對象們被一個簡單的XML文件連在一塊兒,這個XML文件含有到像事務管理器、對象工廠、包含業務邏輯的服務對象、和數據存取對象這些對象的引用。
這篇文章的後面將用例子來把Spring使用這些概念的方法說得更清楚一些。業務層應該負責下面這些事情:
處理應用程序的業務邏輯和業務驗證;
管理事務;
預留和其它層交互的接口;
管理業務層對象之間的依賴;
增長在表現層和持久層之間的靈活性,使它們互不直接通信;
從表現層中提供一個上下文給業務層得到業務服務;
管理從業務邏輯到持久層的實現。
領域模型層
最後,由於咱們討論的是一個不是很複雜的、基於web的應用程序,咱們須要一組能在不一樣的層之間移動的對象。領域對象層由那些表明現實世界中的業務對象的對象們組成,好比:一份訂單、訂單項、產品等等。這個層讓開發者中止創建和維護沒必要要的數據傳輸對象(或者叫做DTOs),來匹配他們的領域對象。例如,Hibernate容許你把數據庫信息讀進領域對象的一個對象圖,這樣你能夠在鏈接斷開的狀況下把這些數據顯示到UI層。那些對象也能被更新和送回到持久層並在數據庫裏更新。並且,你沒必要把對象轉化成DTOs,由於DTOs在不一樣的應用層間移動,可能在轉換中丟失。這個模型使得Java開發者天然地以一種面向對象的風格和對象打交道,沒有附加的編碼。
既然每一個層是互相做用的,咱們就先來建立domain objects。首先,咱們要在這些Object中要肯定那些是須要持久化的,哪些是提供給business logic,那些是顯示接口的設計。 下一步,咱們將配置咱們的持久層而且定義好Hibernate的OR mappings。而後定義好Business Objects。有了這些組成部分以後,咱們將 使用Spring把這些鏈接起來。 最後,咱們提供給Spring一個持久層,從這個持久層裏咱們能夠知道它是如何與業務邏輯層(business service layer)通訊的,以及它是怎樣處理其餘層拋出的異常的。
域對象層(Domain Object Layer)
這層是編碼的着手點,咱們的編碼就從這層開始。 例子中Order 與OrderItem 是一個One—To—Many的關係。 下面就是Domain Object Layer的兩個對象:
· com.meagle.bo.Order.java: 包含了一個Order的概要信息
· com.meagle.bo.OrderLineItem.java: 包含了Order的詳細信息
好好考慮怎你的package命名,這反應出了你是怎樣分層的。 例如 domain objects在程序中可能打包在com.meagle.bo內。 更詳細一點將打包在com. meagle.bo的子目錄下面。business logic應該從com.meagle.serice開始打包,而DAO 對象應該位於com.meagle.service.dao.hibernate。反應Forms和Actions的 持久對象(presentation classes) 應該分別放在com.meagle.action和com.meagle.forms包。 準確的給包命名使得你的classes很好分割而且易於維護,而且在你添加新的classes時,能使得程序結構上保持上下一致。
持久層的配置(Persistence Layer Configuration)
創建Hibernate的持久層 須要好幾個步驟。 第一步讓咱們把BO持久化。 既然Hibernate是經過POJO工做的, 所以Order和 OrderLineItem對象須要給全部的fileds 加上getter,setter方法。 Hibernate經過XML文件來映射(OR)對象,如下兩個xml文件分別映射了Order 和OrderItem對象。(這裏有個叫XDoclet工具能夠自動生成你的XML影射文件)
- Order.hbm.xml
- OrderLineItem.hbm.xml
你能夠在WebContent/WEB-INF/classes/com/meagle/bo目錄下找到這些xml文件。Hibernate的[urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用來告訴程序 應該與哪一個數據庫通訊,該使用哪一個鏈接池或使用了DataSource, 應該加載哪些持久對象。而Session接口是用來完成Selecting,Saving,Delete和Updating這些操做。 後面的咱們將講述SessionFactory和Session是怎樣設置的。
業務層的配置(Business Layer Configuration)
既然咱們已經有了domain objects,接下來咱們就要business service objects了,用他們來執行程序的logic,調用持久層,獲得UI層的requests,處理transactions,而且控制exceptions。 爲了將這些鏈接起來而且易於管理,咱們將使用面向方面的 SpringFramework。 Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依賴設置(setter dependency injection)這些方式(可供選擇),用XML文件將對象鏈接起來。 IoC是一個簡單概念(它容許一個對象在上層接受其餘對象的建立),用IoC這種方式讓你的對象從建立中釋放了出來,下降了偶合度。
這裏是一個沒有使用IoC的對象建立的例子,它有很高偶合度。
圖 2.沒有使用 IoC. A 建立了 B 和 C
而這裏是一個使用IoC的例子,這種方式容許對象在高層能夠建立並進入另一個對象,因此這樣能夠直接被執行。
圖 3. 對象使用了 IoC。 A 包含了接受B,C的 setter方法 , 這一樣達到了 由A建立B,C的目的。
創建咱們的業務服務對象(Building Our Business Service Objects)
Business Object中的Setter方法接受的是接口,這樣咱們能夠很鬆散的定義對象實現,而後注入。 在咱們的案例中,咱們將用一個business service object接收一個DAO,用它來控制domain objects的持久化。 因爲在這個例子中使用了Hibernate,咱們能夠很方便的用其餘持久框架實現 同時通知Spring 有新的DAO可使用了。
在面向接口的編程中,你會明白 「注射依賴」模式是怎樣鬆散耦合你的業務邏輯和持久機制的:)。
下面是一個接口business service object,DAO代碼片斷:
代碼: |
|
注意到這段代碼裏有一個 setOrderDao(),它就是一個DAO Object設置方法(注射器)。 但這裏並無一個getOrderDao的方法,這沒必要要,由於你並不會在外部訪問這個orderDao。這個DAO Objecte將被調用,和咱們的persistence layer 通訊。咱們將用Spring把DAO Object 和 business service object搭配起來的。由於咱們是面向接口編程的,因此並不須要將實現類緊密的耦合在一塊兒。
接下去咱們開始咱們的DAO的實現類進行編碼。 既然Spring已經有對Hibernate的支持,那這個例子就直接繼承HibernateDaoSupport類了,這個類頗有用,咱們能夠參考HibernateTemplate(它主要是針對HibernateDaoSupport的一個用法,譯註:具體能夠查看Srping 的API)。
下面是這個DAO接口代碼:
代碼: |
public interface IOrderDAO { |
咱們仍然要給咱們持久層組裝不少關聯的對象,這裏包含了HibernateSessionFactory和TransactionManager。 Spring 提供了一個 HibernateTransactionManager,他用線程捆綁了一個Hibernate Session,用它來支持transactions(請查看ThreadLocal) 。
下面是HibernateSessionFactory 和 HibernateTransactionManager:的配置:
代碼: |
<bean id="mySessionFactory" |
能夠看出:每一個對象均可以在Spring 配置信息中用<bean>標籤引用。在這裏,mySessionFactory引用了 HibernateSessionFactory,而myTransactionManager引用了 HibernateTransactionManage。 注意代碼中myTransactionManger Bean有個sessionFactory屬性。 HibernateTransactionManager有個sessionFactory setter 和 getter方法,這是用來在Spring啓動的時候實現「依賴注入」 (dependency injection)的。 在sessionFactory 屬性裏 引用mySessionFactory。這兩個對象在Spring容器初始化後就被 組裝了起來了。 這樣的搭配讓你從 單例(singleton objects)和工廠(factories)中解放了出來,下降了代碼的維護代價。mySessionFactory.的兩個屬性,分別是用來注入 mappingResources 和 hibernatePropertes的。一般,若是你在Spring以外使用Hibernate,這樣的設置應 該放在hibernate.cfg.xml中的。 無論怎樣,Spring提供了一個便捷的方式-----在Spring內部配置中併入了 Hibernate的配置。 若是要獲得更多的信息,能夠查閱Spring API。
既然咱們已經組裝配置好了Service Beans,就須要把Business Service Object和 DAO也組裝起來,並把這些對象配到一個事務管理器(transaction manager)裏。
在Spring中的配置信息:
代碼: |
|
圖4 是咱們對象搭建的一個提綱。 從中能夠看出,每一個對象都聯繫着Spring,而且能經過Spring注入到其餘對象。把它與Spring的配置文件比較,觀察他們之間的關係
圖 4. Spring就是這樣基於配置文件,將各個Bean搭建在一塊兒。
這 個例子使用一個TransactionProxyFactoryBean,它定義了一個setTransactionManager()。 這對象頗有 用,他能很方便的處理你申明的事物還有Service Object。 你能夠經過transactionAttributes屬性來定義怎樣處理。 想知道更多仍是參考 TransactionAttributeEditor吧。
TransactionProxyFactoryBean 還有個 setter. 這會被咱們 Business service object(orderTarget)引用, orderTarget定義了 業務服務層,而且它還有個屬性,由setOrderDAO()引用。這個 屬性
Spring 和Bean 的還有一點要注意的: bean能夠以用兩種方式創造。 這些都在單例模式(Sington)和原型模 式(propotype)中定義了。 默認的方式是singleton,這意味着共享的實例將被束縛。 而原形模式是在Spring用到bean的時候允 許新建實例的。當每一個用戶須要獲得他們本身Bean的Copy時,你應該僅使用prototype模式。(更多的請參考設計模式中的單例模式和原形模 式)
提供一個服務定位器(Providing a Service Locator)
既 然咱們已經將咱們的Serices和DAO搭配起來了。咱們須要把咱們的Service顯示到其餘層。 這個一般是在Struts或者Swing這層裏編 碼。一個簡單方法就是用 服務定位器返回給Spring context 。固然,能夠經過直接調用Spring中的Bean來作。
下面是一個Struts Actin 中的服務定位器的一個例子。
代碼: |
|
UI 層配置 (UI Layer Configuration)
這個例子裏UI層 使用了Struts framework. 這裏咱們要講述一下在給程序分層的時候, 哪些是和Struts部分的。咱們就從一個Struts-config.xml文件中的Action的配置信息開始吧。
代碼: |
|
SaveNewOrder 這個Action是用來持久化UI層裏的表單提交過來Order的。這是Struts中一個很典型的 Action; 注意觀察這個Action中exception配置,這些Exceptions也在Spring 配置文件 (applicationContext-hibernate.xml)中配置了(就在 business service object的transactionAttributes屬性裏)。 當異常在業務層被被拋出時,咱們能夠控制他們,並適當的顯示給UI層。
第一個異常,OrderException,在持久層保存order對象失敗的時候被觸發。這將致使事物回滾而且經過BO把異常回傳到Struts這一層。
第二個異常,OrderMinimumAmountException也同第一個同樣。
搭配整和的最後一步 經過是讓你顯示層和業務層相結合。這個已經被服務定位器(service locator)實現了(前面討論過了), 這裏服務層做爲一個接口提供給咱們的業務邏輯和持久層。
SaveNewOrder Action 在Struts中用一個服務定位器(service locator)來調用執行業務方法的。 方法代碼以下:
代碼: |
public ActionForward execute( OrderForm oForm = (OrderForm) form; // See the full source code in the sample app. // in BaseAction. } |
總結 這篇文章在技術和構架方面掩蓋了不少低層的基礎信息, 文章的主要的意圖在於讓你意識到如何給你應用程序分 層。 分層能夠「解耦」你的代碼——容許新的組件被添加進來,並且讓你的代碼易於維護。 這裏用到的技術只是專一於把「解偶」作好。 無論怎樣,使用這樣 的構架可讓你用其餘技術代替如今的層。 例如,你可能不使用Hibernate實現持久化。既然你在DAO中面向接口的編程的,因此你徹底能夠用 iBATIS來代替。或者,你也可能想用Struts外的其餘的技術或者框架替換如今的UI層(轉換久層,實現層並不該該直接影響到你的業務邏輯和業務服 務層)。 用適當的框架搭建你的Web應用,其實也不是一件煩瑣的工做,更主要的是它「解耦」了你程序中的各個層。