徐遇霄
(武漢市長虹橋37-1號 武漢 430064)
霍金曾說:復雜性是21世紀的科學。當代對復雜系統(tǒng)的研究也表明,復雜性是由簡單性進化而來的。那么,我們?nèi)绾螌碗s的難事變?yōu)楹唵蔚囊资?對一般的復雜問題,將其分割為簡單的橫向子問題,就可以達到效果。對于更加復雜的問題,則需要在橫向子問題分割的基礎上,實行縱向分層??v向分層也是一種抽象的分解復雜問題的方法?,F(xiàn)在,一個軟件系統(tǒng),往往是一巨型復雜系統(tǒng)。對于這種復雜系統(tǒng)的分析與實現(xiàn),分層理論認為,降低其復雜性與提高效率的最好辦法是將系統(tǒng)分層實現(xiàn)。從軟件研究和開發(fā)的發(fā)展歷史、現(xiàn)行軟件的體系結構來看,分層方法一直都是軟件研發(fā)普遍適用的基本的思想方法。因此,在軟件體系結構中,把層次性系統(tǒng)作為架構風格,應用的相當廣泛。
SOA的主要特點之一是平臺中立,平臺中立的Java Web服務技術是構建SOA系統(tǒng)一種很自然的選擇。在Java世界中,J2EE多層架構是一個典型的分層體系,同樣,基于Java的SOA系統(tǒng)也可采用分層模型。SOA有3個角色,其中服務請求者是服務的最終消費者,它對服務進行應用,則位于SOA的頂層-應用層。服務注冊中心負責服務的注冊,以便請求者能發(fā)現(xiàn)服務,在一定程度上履行了服務接口的功能。服務提供者構建實現(xiàn)服務的業(yè)務邏輯,部署服務并提供調(diào)用服務的環(huán)境。業(yè)務邏輯都由業(yè)務組件構成,業(yè)務邏輯層應該是獨立的一層。業(yè)務組件需要部署為服務,并要提供服務的描述以及調(diào)用服務的環(huán)境,請求者才能消費服務,因此,在應用層與業(yè)務層之間,可定義服務接口層,以實現(xiàn)業(yè)務層到應用層的平滑過渡。業(yè)務層一般要訪問數(shù)據(jù)庫,但不是直接訪問,可通過一個中間層來進行。中間層的作用是屏蔽訪問不同數(shù)據(jù)庫的差異,使數(shù)據(jù)庫對業(yè)務層是透明的。因此,數(shù)據(jù)庫位于系統(tǒng)的最底層,而業(yè)務層與數(shù)據(jù)庫之間的中間層可定義為數(shù)據(jù)接口層。至此,基于SOA的應用系統(tǒng)從上到下可劃分為如下5層:應用層、服務接口層、業(yè)務層、數(shù)據(jù)接口層和數(shù)據(jù)庫層,如圖1所示。
圖1 基于Java的SOA分層架構
服務接口層為應用層調(diào)用服務提供標準化的接口,從而使得該服務可提供給任何異構平臺和任何本地或者遠程用戶使用。
業(yè)務層主要提供系統(tǒng)的業(yè)務邏輯和控制,由一些基本的組件構成。
數(shù)據(jù)接口層為業(yè)務層提供統(tǒng)一的訪問數(shù)據(jù)庫的方式,以屏蔽業(yè)務層訪問不同數(shù)據(jù)庫的差異。
數(shù)據(jù)庫層完成數(shù)據(jù)的持久化功能。它提供了數(shù)據(jù)信息和數(shù)據(jù)邏輯,所有與數(shù)據(jù)有關的安全性、完整性、數(shù)據(jù)的一致性、并發(fā)操作等都在數(shù)據(jù)庫層。
數(shù)據(jù)接口層和數(shù)據(jù)庫層統(tǒng)稱為數(shù)據(jù)層。
1)數(shù)據(jù)實體類的設計
在數(shù)據(jù)接口層的上一層業(yè)務層中,對數(shù)據(jù)的操作體現(xiàn)在業(yè)務管理類和業(yè)務處理類與業(yè)務數(shù)據(jù)類的交互。業(yè)務數(shù)據(jù)類是數(shù)據(jù)實體類的一部分。為了使業(yè)務層以一致的方式處理數(shù)據(jù),首先,數(shù)據(jù)實體類應該采用一致的數(shù)據(jù)表示方式。在業(yè)務層中,所有的數(shù)據(jù)都由數(shù)據(jù)實體類來統(tǒng)一表示,這些類是基本的JavaBean,被稱為POJO或ValueObject,只有屬性和Get/Set方法,其作用就是供業(yè)務類使用,是業(yè)務類操作的對象。為了增強程序的可讀性并方便記憶,可將類的名稱定義為與表名相同,將類中的屬性名與表的字段名定義相同。這些數(shù)據(jù)類與數(shù)據(jù)庫進行映射,一般將數(shù)據(jù)實體類的屬性映射為數(shù)據(jù)庫中對應表的字段,非原子屬性則映射為表,這種映射關系通常由一個XML映射配置文件來完成。由于基于XML文本的配置文件可以靈活的改變,因此提高了系統(tǒng)的可移植性及易維護性,同時也在數(shù)據(jù)層體現(xiàn)了系統(tǒng)的松耦合性。
2)持久化技術的選擇
目前,在基于Java的程序設計中,常用的主要有以下幾種持久化技術:
(1)BMP(Bean-Managed Persistence),即Bean本身管理持久化。這種方式由在Java組件中嵌入JDBC代碼來實現(xiàn),顯然,這是一種緊耦合的方式。
(2)CMP(Container-Managed Persistence),即容器管理持久化,表示由EJB容器來管理實體EJB的持久化。EJB容器封裝了對象/關系的映射及數(shù)據(jù)訪問細節(jié)。這是一種框架化的持久性機制,在這類機制中,由框架調(diào)用業(yè)務處理的類。這種機制的一個特點就是它提供一個管理環(huán)境,在這個環(huán)境中進行對象持久化。一旦離開這個環(huán)境,代碼就不能運行了。并且,理解并使用EJB的規(guī)范也不是很輕松的事情。
(3)JDO(Java Data Objects),Sun公司制定的描述對象持久化語義的標準API。嚴格的說,JDO并不是對象/關系映射接口,因為它支持把對象持久化到任意一種存儲系統(tǒng)中,包括關系數(shù)據(jù)庫、面向?qū)ο蟮臄?shù)據(jù)庫、基于XML的數(shù)據(jù)庫,以及其他專有存儲系統(tǒng)。由于關系數(shù)據(jù)庫是目前最流行的存儲系統(tǒng),許多JDO的實現(xiàn)都包含了對象/關系映射服務。JDO的出現(xiàn)似乎有了一些改觀,但是,JDO沒有一個好的開源免費實現(xiàn)。好的產(chǎn)品一般都是商業(yè)產(chǎn)品,并且在國內(nèi)沒有銷售和技術支持。JDO也不是一個輕量級封裝,它建立的持久層框架很不完善,造成了JDO感覺比較笨重,使得很多操作方式很是煩瑣,JDO的應用在人們心理上一直布滿陰影。
(4)Hibernate,輕量級的開源ORM模型。它的一大優(yōu)勢就在于可以把被持久化的對象實現(xiàn)成脫離這個持久化環(huán)境依然可以運行的類。Hibenate利用XML文件將應用程序的數(shù)據(jù)實體類與數(shù)據(jù)庫中的表進行映射,并通過框架的內(nèi)部機制對復雜的數(shù)據(jù)操作提供支持,包括記錄的添加、修改和刪除等操作。因此,在基于Java的程序設計中,Hibernate成為持久層流行的框架技術,而它對于構建基于SOA的應用系統(tǒng),也無疑是一個很優(yōu)的選擇。下面簡要介紹Hibernate的原理。
Hibernate是一種比較徹底的Java對象關系映射工具,支持使用各種Java思想,如Inheritance(繼承),Association(關聯(lián)),Composition(組合),Collections(集合)等來實現(xiàn)對象關系映射。它可以直接映射大部分的POJO型的JavaBean,而不需要對它們作任何修改,即使需要修改,最多只在Bean里面加上一些私有訪問方法。它還可以將一個用戶定義的多個類的實例映射到一張表的同一行,甚至可以利用代理模式來簡化載入類的過程。這些功能都大大減少了利用HQL從數(shù)據(jù)庫提取數(shù)據(jù)的代碼編寫量,從而節(jié)約開發(fā)時間和開發(fā)成本。Hibernate利用Reflection機制,在系統(tǒng)啟動時生成SQL語句,進行對象的持久管理。Hibernate對每一種數(shù)據(jù)庫都有對應的Dialect進行操作優(yōu)化,從而提高它在各種情況下的效率。
圖2所示 Hibernate的持久化服務在一個數(shù)據(jù)庫應用中的作用:應用程序通過
圖2 Hibernate持久化原理
Hibernate 連接到數(shù)據(jù)庫,對數(shù)據(jù)進行操作。Hibernate自身通過Properties或類的映射文件(Mapping XML)將數(shù)據(jù)實體類映射到數(shù)據(jù)庫的行。因此Application可以通過持久化的數(shù)據(jù)類直接訪問數(shù)據(jù)庫,而不必使用JDBC和SQL進行數(shù)據(jù)的操作。
Hibernate具有很大的靈活性,界于它的最大模式和最小模式之間的某些功能構件是可選的。在最小模式下,可選擇使用JDBC,可以利用JTA管理自己的事務,也可以使用JNDI。這時Hibernate通過 SessionFactory提供 Session,在 Session中對持久化對象進行操作。在最大模式下,Hibernate在自己的底層管理 JNDI、JDBC和 JTA,在上層向外提供 SessionFactory、Session和 Transaction的接口,供 Client控制Persistent Object之用。
3)數(shù)據(jù)庫訪問的設計
(1)數(shù)據(jù)實體類與表的映射
Hibernate定義了類到數(shù)據(jù)庫的基于XML的映射文件。映射文件中的“class”元素定義了需持久化的類與數(shù)據(jù)庫中表的映射關系,“name”屬性指定了類名,而“table”屬性指定了數(shù)據(jù)庫中的表?!癷d”元素定義了鍵屬性?!皃roperty”元素定義了類的屬性與表中字段的映射。具體的映射文件可見后文的實現(xiàn)部分。
(2)配置 Hibernate
配置Hibernate通過設置其配置文件來完成。該文件描述了數(shù)據(jù)庫的驅(qū)動程序以及數(shù)據(jù)庫的URL等連接數(shù)據(jù)庫的信息。Hibernate在應用程序啟動時自動進行初始化工作。配置描述文件可以是hibernate.cfg.xml或 Hibernate.properties文件。
Hibernate對JDBC進行了封裝,自動進行JDBC連接,并使用SessionFactory來打開數(shù)據(jù)庫的連接。使用Hibernate時,我們可以提供外部連接池,亦可配置Hibernate使用它自己直接支持的池(C3PO,Proxcool)。Hibernate可以根據(jù)用戶的數(shù)據(jù)庫設置一個正確的hibernate.dialect語言。它支持 Oracle、Ms SQL、My SQL 、DB2等多種語言 。Hibernate提供的HQL也支持外部連接查詢,這些連接類型是從SQL中借鑒來的:inner join(內(nèi)連接)、left outer join(左外連接)、right outer join(右外連接)、full join(全連接,并不常用)。但外連接也可通過設置Outer-join屬性為False來禁止,因為使用它會占用過多的資源。
Hibernate可靈活地設置數(shù)據(jù)庫的驅(qū)動程序及數(shù)據(jù)庫的URL。這樣,在進行系統(tǒng)設計時,我們可以不去關心底層采用的是何種數(shù)據(jù)庫。加之我們引入ORM技術,使得業(yè)務邏輯和數(shù)據(jù)邏輯分離。在此二者基礎上,我們就構建了出一個抽象層—數(shù)據(jù)接口層。數(shù)據(jù)接口層的引入一方面增強了系統(tǒng)的靈活性和可移植性,另一方面也體現(xiàn)了SOA的松散耦合性。
(3)使用Hibernate進行數(shù)據(jù)庫訪問
Hibernate運用框架模型如圖3所示。
圖3 Hibernate應用框架模型
其中:*.hbm.xml是數(shù)據(jù)實體類與表的映射文件,*_Access.class是數(shù)據(jù)訪問類文件,*.class是POJO型的數(shù)據(jù)實體類文件。
1)業(yè)務邏輯的實現(xiàn)策略
我們可以將業(yè)務層類分為三大類:業(yè)務管理類、業(yè)務處理類和業(yè)務輔助類,如圖4所示。在數(shù)據(jù)接口層提供的數(shù)據(jù)實體對象和對象的持久性存儲機制的基礎之上,就可以將這些對象根據(jù)業(yè)務需求由業(yè)務層的類組合起來,構建系統(tǒng)的業(yè)務邏輯處理程序。
圖4 業(yè)務層類框架圖
2)服務粒度的選擇
我們可以用服務樹來刻畫服務的粒度。所謂服務樹,是把要部署為服務的功能模塊用樹型結構來進行表示,如圖5網(wǎng)上定購服務樹所示。
圖5 服務樹圖
服務樹清晰地反映出了服務的粒度,是構建SOA系統(tǒng)時決定服務粒度的有力工具。我們可以利用服務樹找到SOA系統(tǒng)最佳的服務粒度方式。
服務接口層通過部署,將業(yè)務層的業(yè)務管理類暴露為服務,因此,業(yè)務管理類所實現(xiàn)的業(yè)務邏輯的粒度就決定了系統(tǒng)服務的粒度。SOA傾向于粗粒度的服務,在進行系統(tǒng)之間的通信時,這有很大的優(yōu)勢,因為粗粒度的服務減少了系統(tǒng)之間的交互,提高了系統(tǒng)的運行效率,特別是異構異地的系統(tǒng)之間的通信。但在進行企業(yè)內(nèi)部應用系統(tǒng)之間集成,或系統(tǒng)內(nèi)部的構建時,粗粒度的服務降低了系統(tǒng)的靈活性,增大了系統(tǒng)的耦合性。所以,我們在構建SOA系統(tǒng)時,要選擇一個合適的服務粒度。
1)Web服務引擎AXIS
Apache可擴展交互系統(tǒng)(Apache eXtensible Interaction System,AXIS)是在基于可配置的消息鏈和Handler對象重新設計SOAP的過程中發(fā)展而來的。它是基于 Java的、最新的SOAP規(guī)范(SOAP 1.2)和SOAP with Attachments規(guī)范的開源實現(xiàn)。圖6表示了AXIS引擎的基礎結構。
圖6 AXIS基礎結構
AXIS可作為Web服務引擎工作于服務接口層,也可作為服務請求方環(huán)境運行于應用層,因此,它是構建基于Java的Web服務的良好選擇。
2)使用AXIS部署服務
使用AXIS將業(yè)務層的組件部署為Web服務有以下3種方式:
(1)最簡單的方式:jws方式
AXIS提供了一種將帶有.jws擴展的Java類部署為Web服務的簡單方式。它的實質(zhì)是AXIS將Servlet引擎中的Java Servlet自動部署為Web服務。常用的Servlet引擎是Apache的 Tomcat容器。這種方式以Java類的源文件為基礎,部署方法很簡單,只須將以.java為擴展名的源文件,重命名為以.jws為擴展名的文件,復制到Axis Web應用程序的主目錄中。當該Web服務被訪問時,Axis會根據(jù).jws文件自動生成相應的 WSDL及SOAP端點,即自動將.jw s文件部署為Web服務,而無需WSDD部署描述符。這種方式也無需編譯該文件,Axis運行庫會自動進行類及其所有方法的編譯。
獲取該服務的WSDL與其它方式相同,只需在訪問該服務的URL后加“?WSDL”參數(shù)即可,如“http://localhost:8080/axis/HelloWorld.jws?WSDL”。
以.jws文件形式創(chuàng)建Web服務的方法,從簡易性及可操作性的角度來看,非常類似于JSP。這種方式一般用于建立單一的或簡易的Web服務。
(2)使用WSDD將JSE組件部署為Web服務
以.jws文件部署基于Java的Web服務雖然既簡單有快捷,但缺乏服務部署的靈活性,例如,我們需要將JSE組件中的某些方法而非全部發(fā)布為Web服務。Axis提供了 Web服務部署描述符(Web Service Deployment Description,WSDD)的方法,可以對Java Web服務進行一些高級的定制部署。該方法需要創(chuàng)建一個部署服務(deployment)的XM L描述文件(*.wsdd)和一個卸載服務(undeployment)的XML描述文件。這些文件將告訴AXIS如何處理對Java Web服務的特定調(diào)用。
(3)使用WSDD將EJB部署為Web服務
在開源的EJB服務器(或容器)中,我們選擇JBoss公司的JBoss服務器。JBoss集成Axis時,需將Axis文件夾復制到JBoss的部署目錄中。另外,我們還要確保Axis能夠為EJB載入類文件,方法是將該EJB的.jar包文件復制一份到Axixlib文件夾中。一般情況下,我們使用Axis將JBoss中的無狀態(tài)會話(Stateless SessionBean)類型的EJB發(fā)布為Web服務,目前可采用如下兩種常用的方法:
①使用基于EJB的WSDD,這種方式同上述第2種情形大致相似,只是WSDD中有更多的元素來描述EJB,因為EJB相對于JSE,有更多的要遵循的規(guī)范。
②使用JBoss的 JBoss.NET模塊,用 XML Web服務描述符來部署。JBoss.NET[29]是JBoss集成了Axis后的部署Web服務的一個工具。利用它進行部署工作要依賴于.wsr文件,該文件可視為打包版的Axis的WSDD。.wsr文件是一個標準的.jar文件,僅包含一個名為META-INTweb_service.xml的XML Web服務描述符。
JBoss公司目前正在進行一個被稱為“JBoss-WS”的項目,其目標是重構JBoss應用服務器,以使用他自己的SOAP協(xié)議棧而不是集成Axis。
應用層客戶端在構建用戶的業(yè)務流程時,一般要先完成調(diào)用服務以及基于XML的數(shù)據(jù)處理兩項任務??蛻舳苏{(diào)用服務大多數(shù)情況下是為了進行數(shù)據(jù)通信。對于服務的請求方和提供方,二者都基于XML的數(shù)據(jù)格式進行通信,因而在調(diào)用服務進行數(shù)據(jù)通信時,需要將用戶關心的數(shù)據(jù)進行串行化或反串行化(AXIS引擎只自動實現(xiàn)SOAP消息的串行化或反串行化)。所謂串行化數(shù)據(jù)是指將應用程序的數(shù)據(jù)格式轉(zhuǎn)換為XML格式,反串行化則反之。根據(jù)數(shù)據(jù)的流向,可分為兩種情形,一是通過調(diào)用服務向服務提供方發(fā)送數(shù)據(jù)(如圖7所示),如向網(wǎng)上商店提交的訂單,需要進行數(shù)據(jù)串行化。
圖7 串行化流程
二是調(diào)用服務從服務提供方獲取數(shù)據(jù)(如圖8所示),如獲取商家的產(chǎn)品信息,這與第一種情形正好相反,需要進行數(shù)據(jù)的反串行化。
圖8 反串行化流程
對于第一種情形,客戶端應用程序先將數(shù)據(jù)串行化為XML格式,然后用SOAP協(xié)議進行封裝,調(diào)用服務發(fā)送即可。對于另一種情形,客戶端一般先接收調(diào)用服務所獲取的基于XML格式的字符串,然后將其反串行化為用戶所需類型的數(shù)據(jù)。
圖9 應用層數(shù)據(jù)處理架構
客戶端在調(diào)用服務發(fā)送數(shù)據(jù),進行數(shù)據(jù)的串行化之前,需要采集原始數(shù)據(jù)。而在調(diào)用服務獲取數(shù)據(jù)并進行反串行化之后,需要顯示數(shù)據(jù)或進行持久化。因此,應用層除了要進行數(shù)據(jù)串行化或反串行化外,還需要實現(xiàn)數(shù)據(jù)的顯示或提交邏輯。對于客戶端,這一處理邏輯可以基于C/S方式,為用戶提供靈活友好的使用界面,進行顯式處理,或直接用程序組件隱式處理。客戶端亦可基于B/S方式,建立精美的Web頁面顯示或提交數(shù)據(jù)。應用層數(shù)據(jù)處理的架構如圖9所示。
本文所論述的應用層側(cè)重于服務調(diào)用的設計,而沒有過多涉及應用系統(tǒng)客戶端的具體實現(xiàn)。因為實際上,客戶端程序都將調(diào)用服務作為函數(shù)(或過程)來實現(xiàn)。系統(tǒng)開發(fā)人員在構建客戶端應用程序時,可以采用B/S或C/S方式,并在其中調(diào)用訪問Web服務的函數(shù),來構建最終的應用系統(tǒng)。而不論是B/S還是C/S,都已經(jīng)是很成熟的模型,這兩種模型也都有非常成熟的技術可以實現(xiàn)。
作為一個剛剛步入實踐的新事物,SOA還面臨著很多的挑戰(zhàn)。SOA還正處在不斷的發(fā)展之中,它的成熟度和完善性還有待于研究人員和企業(yè)在理論和實踐中不斷的加以提高和改善。雖然被稱為是繼面向過程和面向組件的下一代軟件體系結構,但目前還沒有以上兩種架構成熟,且目前的應用才剛剛起步。然而,由于SOA自身具有的優(yōu)勢順應了未來軟件發(fā)展的趨勢,并隨著各大軟件供應商在此展開的深入研究和激烈競爭,它必然會成為成熟的下一代軟件體系架構和主流開發(fā)技術而得到廣泛支持和應用。可以預見在未來的幾年里,SOA將會取得長足的發(fā)展。
[1]胡光.基于Jini的查找服務實現(xiàn)[J].計算機應用研究,2005(2)http://www.bea.com/framework.jsp?CNT=index.htm&FP=/content/solutions/technical/web_services
[2][美]科耶爾.XM L、Web服務和數(shù)據(jù)革命[M].袁勤勇,等譯.清華大學出版社,2003
[3]蔡月茹,柳西玲.Web Service基礎教程[M].北京:清華大學出版社,2005,6
[4]張凱.軟件復雜性與質(zhì)量控制[M].北京:中國財政經(jīng)濟出版社,2005,11
[5]姜璐.復雜系統(tǒng)的層次結構,復雜性研究[M].北京:科學出版社,1993,7
[6]伽瑪,等.設計模式:可復用面向?qū)ο筌浖幕A[M].李英軍,等譯.北京:機械工業(yè)出版社,2000,9
[7][美]尼戈潘,等.Java Web服務開發(fā)[M].龐太剛,陶程,譯.2004,5