其實(shí),就算用Java建造一個(gè)不是很煩瑣的web應用,也不是件輕松的事情。 在構架的一開(kāi)始就有很多事情要考慮。 從高處看,擺在開(kāi)發(fā)者面前有很多問(wèn)題:要考慮是怎樣建立用戶(hù)接口?在哪里處理業(yè)務(wù)邏輯? 怎樣持久化的數據。 而這三層構架中,每一層都有他們要仔細考慮的。 各個(gè)層該使用什么技術(shù)? 怎樣的設計能松散耦合還能靈活改變? 怎樣替換某個(gè)層而不影響整體構架?應用程序如何做各種級別的業(yè)務(wù)處理(比如事務(wù)處理)?
構架一個(gè)Web應用需要弄明白好多問(wèn)題。 幸運的是,已經(jīng)有不少開(kāi)發(fā)者已經(jīng)遇到過(guò)這類(lèi)問(wèn)題,并且建立了處理這類(lèi)問(wèn)題的框架。 一個(gè)好框架具備以下幾點(diǎn): 減輕開(kāi)發(fā)者處理復雜的問(wèn)題的負擔("不重復發(fā)明輪子"); 內部有良好的擴展; 并且有一個(gè)支持它的強大的用戶(hù)團體。 好的構架一般有針對性的處理某一類(lèi)問(wèn)題,并且能將它做好(Do One Thing well)。 然而,你的程序中有幾個(gè)層可能需要使用特定的框架,已經(jīng)完成的UI(用戶(hù)接口) 并不代表你也可以把你的業(yè)務(wù)邏輯和持久邏輯偶合到你的UI部分。 舉個(gè)例子, 你不該在一個(gè)Controller(控制器)里面寫(xiě)JDBC代碼作為你的業(yè)務(wù)邏輯, 這不是控制器應該提供的。 一個(gè)UI 控制器應該委派給其它給在UI范圍之外的輕量級組件。 好的框架應該能指導代碼如何分布。 更重要的是,框架能把開(kāi)發(fā)者從編碼中解放出來(lái),使他們能專(zhuān)心于應用程序的邏輯(這對客戶(hù)來(lái)說(shuō)很重要)。 這篇文章將討論怎樣結合幾種著(zhù)名的框架來(lái)使得你的應用程序做到松弛耦合。 如何建立你的架構,并且怎樣讓你的各個(gè)應用層保持一致。?如何整合框架以便讓每個(gè)層在以一種松散偶合的方式彼此作用而不用管低層的技術(shù)細節?這對我們來(lái)說(shuō)真是一種挑戰。 這里討論一個(gè)整合框架的策略( 使用3 種受歡迎的開(kāi)源框架) :表示層我們用Struts; 業(yè)務(wù)層我們用Spring;而持久層則用Hibernate。 你也可以用其他FrameWork替換只要能得到同樣的效果。 見(jiàn)圖1 (框架組合示意圖) 應用程序的分層 大部分的Web應用在職責上至少能被分成4層。 這四層是:presentation(描述),persistence(持久),business(業(yè)務(wù))和domain model(域模塊)。每個(gè)層在處理程序上都應該有一項明確的責任, 而不應該在功能上與其它層混合,并且每個(gè)層要與其它層分開(kāi)的,但要給他們之間放一個(gè)通信接口。 我們就從介紹各個(gè)層開(kāi)始,討論一下這些層應該提供什么,不應該提供什么。 表示層(The Presentation Layer) 一般來(lái)講,一個(gè)典型的Web應用的的末端應該是表示層。 很多Java發(fā)者也理解Struts所提供的。 象業(yè)務(wù)邏輯之類(lèi)的被打包到org.apache.struts.Action., 因此,我們很贊成使用Struts這樣的框架。 下面是Struts所負責的: * 管理用戶(hù)的請求,做出相應的響應。 * 提供一個(gè)Controller ,委派調用業(yè)務(wù)邏輯和其它上層處理。 * 處理異常,拋給Struts Action * 為顯示提供一個(gè)模型 * UI驗證。 以下條款,不該在Struts顯示層的編碼中經(jīng)常出現。 它們與顯示層無(wú)關(guān)的。 * 直接的與數據庫通信,例如JDBC調用。 * 與你應用程序相關(guān)聯(lián)的業(yè)務(wù)邏輯以及校驗。 * 事物管理。 在表示層引入這些代碼,則會(huì )帶來(lái)高偶合和麻煩的維護。 持久層(The Persistence Layer) 典型的Web應用的另一個(gè)末端是持久層。這里通常是程序最容易失控的地方。開(kāi)發(fā)者總是低估構建他們自己的持久框架的挑戰性。系統內部的持續層不但需要大量調試時(shí)間,而且還經(jīng)常缺少功能使之變得難以控制,這是持久層的通病。 還好有幾個(gè)ORM開(kāi)源框架很好的解決了這類(lèi)問(wèn)題。尤其是Hibernate。 Hibernate為java提供了OR持久化機制和查詢(xún)服務(wù), 它還給已經(jīng)熟悉SQL和JDBC API 的Java開(kāi)發(fā)者一個(gè)學(xué)習橋梁,他們學(xué)習起來(lái)很方便。 Hibernate的持久對象是基于POJO和Java collections。此外,使用Hibernate并不妨礙你正在使用的IDE。 請看下面的條目,你在持久層編碼中需要了解的。 * 查詢(xún)對象的相關(guān)信息的語(yǔ)句。 Hibernate通過(guò)一個(gè)OO查詢(xún)語(yǔ)言(HQL)或者正則表達的API來(lái)完成查詢(xún)。 HQL非常類(lèi)似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。 你需要學(xué)習一些新的HQL語(yǔ)言; 不管怎樣,他們容易理解而文檔也做的很好。 HQL是一種對象查詢(xún)的自然語(yǔ)言,花很小的代價(jià)就能學(xué)習它。 * 如何存儲,更新,刪除數據庫記錄。 * 象Hibernate這類(lèi)的高級ORM框架支持大部分主流數據庫,并且他們支持 Parent/child關(guān)系,事物處理,繼承和多態(tài)。 業(yè)務(wù)層(The Business Layer) 一個(gè)典型Web應用的中間部分是業(yè)務(wù)層或者服務(wù)層。 從編碼的視角來(lái)看,這層是最容易被忽視的一層。 而我們卻往往在UI層或持久層周?chē)吹竭@些業(yè)務(wù)處理的代碼,這其實(shí)是不正確的,因為它導致了程序代碼的緊密偶合,這樣一來(lái),隨著(zhù)時(shí)間推移這些代碼很難維護。幸好,針對這一問(wèn)題有好幾種Frameworks存在。 最受歡迎的兩個(gè)框架是Spring和PicoContainer。 這些為也被稱(chēng)為microcontainers,他們能讓你很好的把對象搭配起來(lái)。 這兩個(gè)框架都著(zhù)手于‘依賴(lài)注射‘(dependency injection)(還有我們知道的‘控制反轉‘Inversion of Control=IoC)這樣的簡(jiǎn)單概念。 這篇文章將關(guān)注于Spring的注射(譯注:通過(guò)一個(gè)給定參數的Setter方法來(lái)構造Bean,有所不同于Factory), Spring還提供了Setter Injection(type2),Constructor Injection(type3)等方式供我們選擇。 Spring把程序中所涉及到包含業(yè)務(wù)邏輯和Dao的Objects——例如transaction management handler(事物管理控制)、Object Factoris(對象工廠(chǎng))、service objects(服務(wù)組件)——都通過(guò)XML來(lái)配置聯(lián)系起來(lái)。 后面我們會(huì )舉個(gè)例子來(lái)揭示一下Spring 是怎樣運用這些概念。 業(yè)務(wù)層所負責的如下: * 處理應用程序的 業(yè)務(wù)邏輯和業(yè)務(wù)校驗 * 管理事物 * 允許與其它層相互作用的接口 * 管理業(yè)務(wù)層級別的對象的依賴(lài)。 * 在顯示層和持久層之間增加了一個(gè)靈活的機制,使得他們不直接的聯(lián)系在一起。 * 通過(guò)揭示 從顯示層到業(yè)務(wù)層之間的Context來(lái)得到business services。 * 管理程序的執行(從業(yè)務(wù)層到持久層)。 域模塊層(The Domain Model Layer ) 既然我們致力于的是一個(gè)不是很復雜的Web的應用, 我們需要一個(gè)對象集合,讓它在不同層之間移動(dòng)的。 域模塊層由實(shí)際需求中的業(yè)務(wù)對象組成 比如, OrderLineItem , Product等等。 開(kāi)發(fā)者在這層 不用管那些DTOs,僅關(guān)注domain object即可。 例如,Hibernate允許你將數據庫中的信息存放入對象(domain objects),這樣你可以在連接斷開(kāi)的情況下把這些數據顯示到UI層。 而那些對象也可以返回給持續層,從而在數據庫里更新。 而且,你不必把對象轉化成DTOs(這可能似的它在不同層之間的在傳輸過(guò)程中丟失),這個(gè)模型使得Java開(kāi)發(fā)者能很自然運用OO,而不需要附加的編碼。 。
聯(lián)系客服