High-level architecture design(總體架構設計)
設計Web應用系統的下一步是總體的架構設計。它包括將應用程序細分為功能組件,將這些組件劃分成若干層。總體架構設計對於具體技術使用是中立的。
MultitIEred architecture(多層架構)
多層架構把整個系統劃分成明顯的功能單元:客戶端,表示層,業務邏輯,綜合(Integration),EIS。這種架構確保了責任的明確劃分,使系統更加易於維護和擴展。三層或多層系統被證明比沒有業務邏輯層的c/s系統更加靈活和可擴展。
客戶層是數據模型被消費和表示的地方。對於一個Web應用來說,客戶層通常是Web浏覽器。基於浏覽器的瘦客戶端沒有包含表示邏輯,它要依靠於表示層。
表示層將業務邏輯層的服務暴露給用戶。它知道如何處理一個客戶端的請求,如何同業務邏輯層交互,如何選擇下一個vIEw去顯示。
業務邏輯層包含了一個應用程序的業務對象和業務服務。它從表示層收到請求,根據請求處理響應的業務邏輯。業務邏輯層組件大大受益於系統級服務(比如安全管理,事務管理,資源管理)。
集成層是業務邏輯層和EIS(Enterprise Information System)層之間的一座橋梁。它把同EIS層交互的邏輯封裝起來。有時候把集成層和業務邏輯層合起來稱作中間層。
應用程序數據在EIS層持久化。它包括關系數據庫,對象數據庫和遺留系統。
JCatalog的架構設計
應用程序使用了一個多層非分布式的框架,上圖向我們顯示了應用層次是如何劃分的,每一層使用的具體技術。這張圖同時作為示例應用程序的部署圖。對於一個配置的架構,表示層,業務邏輯層,集成層都位於同一個Web容器中。定義良好的接口隔離每一層的職責。配置的架構讓應用簡單,可擴展。
對於表示層,經驗告訴我們最佳的方法是選擇一個已經存在的,經過考驗的Web應用框架,而不是自己設計和構建一個框架。我們有一些Web應用框架可供選擇,比如Struts, WebWork, JSF。我們為JCatalog選擇JSF作為表示層框架。
無論EJB還是POJO都可以用來構建業務邏輯層。如果應用程序是分布式的,則擁有遠程接口的EJB是一個很好的選擇。而我們的JCatalog是一個典型的沒有遠程訪問需求的Web應用,所以在Spring框架下的POJO被我們用來實現業務邏輯層。
集成層在關系數據庫上處理數據的持久化工作。有不同的方案可以用來實現集成層:
◆Pure JDBC:這是最靈活的方案;然而底層的JDBC用起來十分笨重,而且劣質的JDBC代碼性能也不好。
◆Entity beans:對於隔離數據訪問代碼和處理O/R映射數據持久化,CMP是一個很昂貴的方案。它是一個以app server為中心的方案。一個entity bean不會使應用依賴於某個數據庫,卻會讓應用依賴於某個EJB容器。
◆O/R mapping框架:O/R mapping框架是一個以對象為中心的實現數據持久化的方案。以對象為中心的應用很容易開發而且非常的輕便。在這個領域有不少的現成框架:JDO, Hibernate, TopLink, CocoBase等等。我們在本應用中使用Hibernate。
現在我們結合每一層來討論一下具體的設計問題。因為JSF是相對新的技術,我們會重點討論它的表示層和JSF,表示層收集用戶的輸入,表示數據,控制頁面導航,將用戶輸入委托給業務邏輯層。表示層也能夠驗證用戶輸入和維護應用會話狀態。在下面我們會討論表示層的設計考慮事項和模式,以及為什麼我們選擇JSF來實現JCatalog的表示層。
1.Model-VIEw-Controller
MVC是Java藍皮書強烈建議的交互型應用程序使用的結構設計模式。MVC分割設計關注,從而能夠減少代碼的重疊,集中控制,使應用更加可擴展。MVC同時幫助不同技能的開發者集中於他們擅長的技能方面,通過清晰定義的接口合作在一起。MVC是表示層的結構設計模式。
2.JavaServer Faces
JSF 是面向基於Java的Web應用而開發的server-side的UI組件框架。JSF包括了一組API,這些API用來表現UI組件以及保持它們狀態;處理事件,服務器端的驗證,以及數據轉換;定義頁面導航;支持國際化和Accessibility;以及對這些功能提供可擴展性。同時它還包括兩個JSP custom tag libraryIEs,用來在JSP頁面中表示UI組和關聯組件與服務器端對象。(實際上JSF現在是一個規范和一組接口以及他提供的參考實現,你也可以自己做你自己的JSF實現,當然難度比較大,如果後面沒特指的話“實現”指的就是自帶的參考實現)
3.JSF和MVC
JSF非常適用於基於MVC的表示層框架。它對行為和表示有著清晰的劃分。它支持我們熟悉的UI組件和Web層的概念,卻不會把你限制在某些腳本技術或標記語言上。
JSF 的backing beans是model層(更多關於backing beans在後面的章節)。它們也可以包含動作,這些動作是作為控制器層的一個擴展以及把用戶的請求代理給業務邏輯層。請注意,從整個應用程序的框架來看,業務邏輯層也常常被稱為model層。(注意和這裡的model層區別開)包含JSF標簽的JSP頁面是作為VIEw層。而Faces Servlet則提供controller的功能。
為什麼使用JSF?
JSF不僅僅是另一個Web框架,下面是它與一般的Web框架的不同:
◆象Swing一樣的面向對象的Web應用開發:服務器端聲明的,有event listeners和handlers的UI組件模型(就像Swing的組件),促使能夠面向對象的Web應用開發。
◆Backing-bean management:Backing bean是在頁面中與UI組件關聯對應的JavaBeans。Backing bean management將UI組件對象的定義,與保持數據執行應用相關處理的對象區分開來。JSF的具體實現在恰當的范圍內儲存和管理這些backing- bean的實例。
◆可擴展的UI組件模型:組成JSF應用的JSF UI組件是可配置,可重用的元素。你可以繼承這些標准的UI組件來開發更為復雜的組件,比如menu bar,tree組件等等。
◆靈活的表現模型:Renderer把UI組件的功能和它的vIEw分開。不同的Renderer可以被創造出來,用來定義同一種客戶端或不同客戶端的同一個組件的不同的外觀。(簡單介紹一下,也就是說你可以定義HTMLRenderer, WMLRenderer來對同一組件生成Html和WML格式的外觀。)
◆可擴展的轉換和驗證模型:你可以在標准的converter和validator的基礎上開發你的converter和validator提供更強大的功能。
盡管JSF很強大,但它現在還不成熟。JSF自帶的component, converter, validator是很基本簡單的。而且每一個組件一個的validation model還不能處理組件和validator之間多對多的validation。JSF標簽同JSTL還不能無縫連接。
在下面的章節中,我們將討論用JSF實現JCatalog的關鍵部分和設計決定。首先我們討論一下JSF中managed bean和backing bean的定義和使用。然後再介紹在JSF中如何處理安全
Managed bean, backing bean, vIEw object, and domain object model
JSF 引入了兩個新概念:managed bean和backing bean。JSF提供了強大的管理bean的機制。一個被JSF管理的JavaBean對象叫做managed bean。一個managed bean描述了一個bean如何創建和管理的,這些和bean的功能無關。
Backing bean定義了頁面上的UI組件的屬性和處理邏輯。每一個backing bean的屬性對應一個組件或者組件的值。Backing bean同時定義了一組執行組件功能的方法,比如驗證組件的數據,處理組件觸發的事件,當組件activate時處理與導航相關的操作。
一個典型的JSF應用中的每一頁面都有一個backing bean。然而,實際中強制頁面和backing bean的一對一關系不是一個好的做法。它會導致類似代碼重復的問題。實際情況中,一些頁面也許會共享同一個backing bean。例如在JCatalog中,CreateProduct和EditProduct頁面共享同一個ProductBean定義。
一個View對象是一個只在表示層使用的model對象。它包含著必須在View層顯示的數據,包含著驗證用戶輸入,處理事件,同業務邏輯層交互的邏輯。在基於JSF的應用中,backing bean就是view對象。在本文中,backing bean和vIEw對象是可互換的概念。與 Struts中的ActionForm和Action概念相比,使用JSF中的backing bean開發更加符合OO設計習慣。一個backing bean不僅僅包含顯示數據,還包括與這些數據相關的行為。而在Struts中,ActionForm和Action分別包含數據和邏輯。
我們大家都聽說過domain object model(域對象模型)。那麼domain object model和view object有什麼不同呢?在一個簡單的Web應用中,一個域對象模型經常穿越所有的層使用。然而在稍復雜的Web應用中,一個獨立的view object是很需要的。Domain object model是關於業務對象(BO)的,應該屬於業務邏輯層。它包含業務數據和與特定業務對象關聯的業務邏輯。一個view object包含著顯示相關的數據和行為。JCatalog的ProductListBean就是view object的一個好例子。它包含著表示層的數據和邏輯,比如分頁相關的數據和邏輯。將vIEw object和domain object model分開的一個缺點就是必須在兩個對象模型之間進行data mapping。在JCatalog中,ProductBeanBuidler和UserBeanBuilder使用了基於反射的Commons- BeanUtils包來實現data mapping。
安全
目前,JSF並沒有內建的安全特性。示例應用的安全需求是很簡單的:僅當用戶要登錄到administration intranet時需要基於用戶名密碼的認證,而且不需要授權。
對於在JSF中的用戶認證,有以下方案:
◆使用一個backing bean基類:這各方案很簡單,但是會讓backing beans依賴於這個繼承結構。(也就是backing bean都繼承這個基類)
◆使用一個JSF VIEwHandler包裝類:這個方案會把安全邏輯緊緊地限制在JSF這個特殊的Web層技術上。
◆使用servlet filter:一個JSF應用和其他的基於Java的Web應用沒什麼區別,因此一個filter就是處理認證檢查的最好地方。這種方案安全邏輯不會綁定到特定Web應用上。
在示例應用中,SecurityFilter類處理用戶的認證。目前,受保護的資源只包括三個頁面,所以為了簡單起見,把它們的位置硬編碼到Filter類裡面了,作為改進你可以把具體的安全規則和受保護的資源寫入配置文件中。