http://blog.csdn.net/slnqnd/article/details/1772910/
Struts2.0 +Hibernate 3.2 +Spring 2.0
一. Struts
1.定義
它是使用 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)
2.結構
在 struts+hibernate+spring 三層結構模型中處於表現層
Struts框架的元件結構圖
(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圖,分別進行介紹,並且看看它們是如何結合在一起的。
- Controller:控制器對使用者的輸入作出反應。它建立並設定模型。控制器的作用是從客戶端接受請求,並且選擇執行相應的業務邏輯,然後把響 應結果送回到客戶端。在Struts中Controller功能由圖中ActionServlet和ActionMapping物件構成:核心是一個 Servlet型別的物件ActionServlet,它用來接受客戶端的請求。ActionServlet包括一組基於配置的 ActionMapping物件,每個ActionMapping物件實現了一個請求到一個具體的Model部分中Action處理器物件之間的對映。
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 如何使用這些擴充套件的類。這種方法有幾個優點:
- 應用程式的整個邏輯流程都儲存在一個分層的文字檔案中。這使得人們更容易檢視和理解它,尤其是對於大型應用程式而言。
- 網頁設計人員不必費力地閱讀 Java 程式碼來理解應用程式的流程。
- Java 開發人員也不必在更改流程以後重新編譯程式碼。
可以通過擴充套件 ActionServlet 來新增 Command 功能。
ActionForm 類
ActionForm 維護 Web 應用程式的會話狀態。 ActionForm 是一個抽象類,必須為每個輸入表單模型建立該類的子類。當我說 輸入表單模型 時,是指 ActionForm 表示的是由 HTML 表單設定或更新的一般意義上的資料。例如,您可能有一個由 HTML 表單設定的 UserActionForm。Struts 框架將執行以下操作:
- 檢查 UserActionForm 是否存在;如果不存在,它將建立該類的一個例項。
- Struts 將使用 HttpServletRequest 中相應的域設定 UserActionForm 的狀態。沒有太多討厭 的 request.getParameter() 呼叫。例如,Struts 框架將從請求流中提取 fname ,並調 用 UserActionForm.setFname() 。
- Struts 框架在將 UserActionForm 傳遞給業務包裝 UserAction 之前將更新它的狀態。
- 在將它傳遞給 Action 類之前,Struts 還會對 UserActionForm 呼叫 validation() 方法進行表單狀態驗證。 注: 這並不總是明智之舉。別的網頁或業務可能使用UserActionForm ,在這些地方,驗證可能有所不同。在 UserAction 類中進行狀態驗證可能更好。
- 可在會話級維護 UserActionForm 。
注:
- struts-config.xml 檔案控制 HTML 表單請求與 ActionForm 之間的對映關係。
- 可將多個請求對映到 UserActionForm 。
- UserActionForm 可跨多頁進行對映,以執行諸如嚮導之類的操作。
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系統時可以大大加快開發的速度。在開發時可以採用的一個開發流程如下:
- 收集和定義應用需求。
- 基於資料採集和顯示的原則定義和開發"螢幕顯示"需求 。
- 為每一個"螢幕顯示"定義訪問路徑。
- 定義ActionMappings建立到應用業務邏輯之間的聯絡。
- 開發滿足"螢幕顯示"需求的所有支援物件。
- 基於每一個"螢幕顯示"需求提供的資料屬性來建立對應的ActionForm物件
- 開發被ActionMapping呼叫的Action物件。
- 開發應用業務邏輯物件 (Bean,EJB,等等)。
- 對應ActionMapping設計的流程建立JSP頁面。
- 建立合適的配置檔案struts-config.xml , web.xml。
- 開發/測試/部署
具體在使用Struts框架時,對應各個部分的開發工作主要包括:
- Model部分:採用JavaBean和EJB元件,設計和實現系統的業務邏輯。根據不同的請求從Action派生具體Action處理物件。完成"做什麼"的任務來呼叫由Bean構成的業務元件。建立由ActionForm 的派生類實現對客戶端表單資料的封裝。
- Controller部分:Struts為我們提供了核心控制部分的實現。我們只需要配置ActionMapping物件
- View部分:為了使用Model中的ActionForm 物件,我們必須用Struts提供的自定義標記建立HTML 表單。利用 Struts提供的自定義標記庫編寫使用者介面把應用邏輯和顯示邏輯分離。Struts框架通過這些自定義標記建立了View和Model之間的聯絡。 Struts的自定義標記還提供了很多定製頁面的功能。
- 同時需要編輯兩個配置檔案:web.xml和struts-config.xml。通過它們配置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)
- 仍處於發展初期
Struts 開發仍處於初級階段。他們正在向著發行版本 1.0 而努力,但與任何 1.0 版本一樣,它不可能盡善盡美。 - 仍在變化中
這個框架仍在快速變化。Struts 1.0 與 Struts 0.5 相比變化極大。為了避免使用不贊成使用的方法,您可能隔一天就需要下載最新的 Struts。在過去的 6 個月中,我目睹 Struts 庫 從 90K增大到 270K 以上。由於 Struts 中的變化,我不得不數次修改我的示例,但我不保證我的示例能與您下載的 Struts 協同工 作。 - 正確的抽象級別
Struts 是否提供了正確的抽象級別?對於網頁設計人員而言,什麼是正確的抽象 級別呢?這是一個用 $64K 的文字才能解釋清楚的問題。在開發網頁的過程中,我們是否應該讓網頁設計人員訪問 Java 程式碼?某些框架 (如 Velocity)說不應該,但它提供了另一種 Web 開發語言讓我們學習。在 UI 開發中限制訪問 Java 有一定的合理性。最重要的是, 如果讓網頁設計人員使用一點 Java,他將使用大量的 Java。在 Microsoft ASP 的開發中,我總是看到這樣的情況。在 ASP 開發中,您應該建立 COM 物件,然後編寫少量的 ASP 指令碼將這些 COM 物件聯絡起來。 但是,ASP 開發人員會瘋狂地使用 ASP 指令碼。我會聽到這樣的話,“既然我可以用VBScript 直接編寫 COM 物件,為什麼還要 等 COM 開發人員來建立它呢?”通過使用標記庫,Struts 有助於限制 JSP 檔案中所需的 Java 程式碼的數量。Logic Tag 就是這樣的一種庫,它對有條件地生成輸出進行管理,但這並不能阻止 UI 開發人員對 Java 程式碼的狂熱。無論您決定使用哪種型別的框架,您 都應該瞭解您要在其中部署和維護該框架的環境。當然,這項任務真是說起來容易做起來難。 - 有限的適用範圍
Struts 是一種基於 Web 的 MVC 解決方案,所以必須用 HTML、JSP 檔案和 servlet 來實現它。 - J2EE 應用程式支援
Struts 需要支援 JSP 1.1 和 Servlet 2.2 規範的 servlet 容器。僅憑這一點遠不能解決您的全部安裝問題,除非使用 Tomcat 3.2。我用 Netscape iPlanet 6.0 安裝這個庫時遇到一大堆問題,按理說它是第一種符合 J2EE 的應用程式伺服器。我建議您在遇到問題時訪問 Struts 使用者郵件列表的歸檔 資料(請參閱 參考資源)。 - 複雜性
在將問題分為幾個部分的同時也引入了複雜性。毫無疑問,要理解 Struts 必須接受一定的培訓。隨著變化的不斷加入,這有時會令人很沮喪。歡迎訪問本網站。 - 在何處...
我還能指出其他問題,例如,控制器的客戶端驗證、 可適用工作流程和動態策略模式在什麼地方?但是,目前這太容易成為吹毛求疵的問題,有些問題是無關緊要的,或者說應該對 1.0發行版提這些問題。隨 著 Struts 小組的不斷努力,到您閱讀本文時 Struts 說不定已經有了這些功能,或者它很快就會具有這些功能。
二. 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 框架的基本功能。核心容器的主要元件是 BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉 (IOC) 模式將應用程式的配置和依賴性規範與實際的應用程式程式碼分開。
- Spring 上下文:Spring 上下文是一個配置檔案,向 Spring 框架提供上下文資訊。Spring 上下文包括企業服務,例如 JNDI、EJB、電子郵件、國際化、校驗和排程功能。
- Spring AOP:通過配置管理特性,Spring AOP 模組直接將面向方面的程式設計功能整合到了Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何物件支援 AOP。 Spring AOP模組為基於 Spring 的應用程式中的物件提供了事務管理服務。通過使用 Spring AOP,不用依賴 EJB 元件,就可以將宣告性事務管理整合到應用程式中。
- Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同資料庫供應商丟擲的錯誤訊息。異常層次結構簡化了錯誤處理,並且極大地降低了 需要編寫的異常程式碼數量(例如開啟和關閉連線)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構。
- Spring ORM:Spring 框架插入了若干個 ORM 框架,從而提供了 ORM 的物件關係工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。
- Spring Web 模組:Web 上下文模組建立在應用程式上下文模組之上,為基於 Web 的應用程式提供了上下文。所以,Spring 框架支援與 Jakarta Struts 的整合。Web 模組還簡化了處理多部分請求以及將請求引數繫結到域物件的工作。
- Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程式的 MVC 實現。通過策略介面,MVC 框架變成為高度可配置的,MVC 容納了大量檢視技術,其中包括JSP、Velocity、Tiles、iText 和 POI。
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應用,其實也不是一件煩瑣的工作,更主要的是它“解耦”了你程式中的各個層。