天天看點

一種優雅的流行架構:Struts+Spring+Hibernate

   用java來建立一個很有 價值 的 web  應 用不是一個簡單的任務。在架構這個應用時要考慮很多的因素和問題。從更高的層次來看,開發人員面臨着關于如何建構使用者接口,何處駐留業務邏輯,以及如何實 現資料持久性這些問題。這3層都有各自的問題需要回答。而每一層又需要實作那些技術?應用如何設計來進行松散耦合并能進行靈活變更?應用架構是否允許某一 層變更而不影響到其它的層次?應用應該如何處理容器一級的 服務 比如事務?

 在為你的應用建立一個架構之前有許多問題需要澄清。幸運的是,有很多開發者都意識到這個問題,并建立了很多架構來解決這些問題。一個良好的架構可以讓開發人員減輕重建立立解決複雜問題方案的負擔和精力;它可以被擴充以進行内部的 定制 化;并且有強大的使用者 社群來 支援它。架構通常能很好的解決一個問題。然而,你的應用是分層的,可能每一個層都需要各自的架構。僅僅解決UI問題并不意味着你能夠很好的将業務邏輯和持 久性邏輯和UI 元件很好的耦合。例如,你不應該使具有JDBC代碼的業務邏輯放入控制器之中,這不是控制器應該提供的功能。一個UI 控制器應該是輕量化的元件,由它代表對UI範圍之外的其它應用層的服務調用。良好的架構自然地形成代碼分離的原則。更為重要的是,架構減輕了開發人員從頭 建構持久層代碼的精力,進而集中精力來應用邏輯上,這對用戶端來說更為重要。

  本文讨論了如何結合幾個著名的架構來達到松散耦合,如何設計你的架構,以及如何達到各個層次的一緻性設計。面臨的挑戰是,将架構整合起來,以使 每一層都向另外的層次以一種松散的方式來暴露接口,而不管底層功能使用的是什麼技術。本文還讨論整合3種著名開源架構的一種政策。對表現層,我們使用 Struts;業務層使用Spring;對于持久層我們使用的是Hibernate。你盡可以取代這裡的某個架構而使用你喜歡的架構已達到同樣的效果。圖 1顯示了架構被整合起來時,從最高層次看到的視圖。

  應用層

  許多設計良好的web  應用,可以被按職責分為四層。這些層次是表現層、持久層、業務層、和領域模型層。每一個層次都有其獨特的職責,不能把各自的功能與其它層次相混合。每一個應用層都應該和其它層隔離開來,但允許使用接口在層間進行 通信 。我們開始來看看每個層,并讨論一下它們各自都應該提供什麼和不應該提供什麼。

  表現層

  一個典型的web 應用的末端是表現層。許多Java 開發者都知道Struts 提供了什麼東西。然而,太多時候,耦合代碼比如業務邏輯被放進org.apache.struts.Action中。是以,我們先總結一下Struts 之類的架構應該提供什麼。下面就是Struts 的職責所在:

  ◆管理使用者的請求和響應

  ◆提供一個控制起來将調用委托到業務邏輯和其他上遊處理

  ◆将來自于抛出例外的其他層的例外處理到Struts Action 中

  ◆組裝可以在視圖中表現的模型對象

  ◆執行UI 校驗

  下面是一些經常可以使用Struts進行編碼但是不應該和表現層關聯的事情:

  ◆直接和資料庫互動,比如JDBC 調用

  ◆與應用相關的業務邏輯和校驗

  ◆事務管理

  ◆在表現層中引入這些類型的代碼将導緻類型耦合和維護負擔。

  持久層

  一個典型Web應 用的另一端是持久層。這也是應用中最容易很快失控的地方。開發者通常低估了自己建構自己的持久層架構的挑戰。一個定制的,内部開發的持久層不僅需要大量的 開發時間,并且通常缺乏功能和難以管理。目前有許多解決這些問題的開源對象關系映射 (ORM) 架構。特别地, Hibernate 架構就允許Java中的對象-關系的持久性和查詢服務。Hibernate 對已經熟悉了SQL 和JDBC API 的Java開發者來或具有中度的學習曲線。Hibernate 的持久對象基于POJO和Java 群集(collections)。此外,使用Hibernate 不和你的IDE接口。下面列出了你需要在持久性架構中編寫的代碼類型:

 查詢關系資訊到對象中。Hibernate 是通過稱為HQL的OO查詢語言,或者使用更有表現能力的規則API,來完成這個工作的。除了使用對象而不是表,使用字段而不是列的方式,HQL非常類似于 SQL。也有一些新的特定的HQL 語言特征需要 學習 ;但是,它們是很容易了解和良好編寫的。HQL 是一種用于查詢對象的自然語言,而對象,隻需要很少的學習曲線吧。 存儲、更新和删除存儲在資料庫中的資訊

  進階的對象關系映射架構比如Hibernate支援大部分主流SQL資料庫,它們支援父/子關系,事務,繼承和多态。

  下面是應該在持久層避免的一些事情:

  ◆業務邏輯應該置于應用的更高層中。這裡隻允許資料通路方法。

  ◆不應該使持久邏輯和表現邏輯耦合。避免表現元件如JSP 或者基于servlet的類中的邏輯直接和資料通路進行 通信 。通過将持久性邏輯隔離在其自己的層中,應用将具有更加靈活的修改性而不影響到其他層的代碼。例如, Hibernate 可以使用其他持久架構和API代替,而不需要修改其它層中的代碼。

  業務層

  典型的Web 應用的中間元件一般是業務層和 服務 層。 從程式設計的角度來說,service layer經常被忽略。這種類型的代碼散布于UI表現層和持久層并不是不多見。這些都不是正确的地方因為它導緻了緊密耦合的應用和難以維護的代碼。幸運的 是,大多數架構都解決了這個問題。這個空間内最流行的兩個架構是Spring 和PicoContainer。它們都被視為是具有非常小的足迹(footprint)并且決定如何将你的對象整合在一起的微容器 (microcontainer)。這些架構都建立在一種叫做依賴性注入(dependency injection) (也稱控制反轉(inversion of control:IOC))的簡單概念之上。我們将關注Spring中通過針對命名配置參數的bean屬性的setter 注入的使用。Spring 也允許一種更加進階的構造器注入(constructor injection)形式作為setter injection 的可選替代。對象通過簡單的XML 檔案進行連接配接,該配置檔案包含對各種對象的引用,比如事務管理 處理器 (transaction management handler),對象工廠,包含業務邏輯的服務對象,以及資料通路對象(DAO)。我們随後會用一些例子來澄清Spring中使用這些改變的方式。業務層應該負責下面的問題:

  ◆處理應用的業務邏輯和業務校驗

  ◆管理事務

  ◆允許與其他層進行互動的接口

  ◆管理業務級對象之間的依賴性

  ◆加入了表現和持久層之間的靈活性,以便它們不需要彼此進行直接通信

  ◆從表現層暴露上下文給業務層以獲得業務服務

  ◆管理從業務層到表現層的實作

  領域模型層

  最後,因為我們要解決實際的問題的web應 用,我們需要一套在不同的層間移動的對象。領域模型層包含的是表達實際業務對象的對象,比如Order, OrderLineItem, Product 等等。這一層允許能讓開發者不再建構和維護不必要的資料傳輸對象DTO來比對其領域對象。例如, Hibernate允許你讀取資料庫資訊到一個領域對象的對象圖中,以便你可以在離線的情況下将其表現在UI層中。這些對象可以被更新并跨過表現層發送回 去,然後進行資料庫更新。另外,你不再需要将對象轉變成DTO,因為它們在不同的層間移動時可能會丢失事務。這種模型允許Java 開發者能夠以OO風格的方式很自然的處理對象,而不用編寫額外的代碼。

繼續閱讀