在 SOA 架構(gòu)中,程序員經(jīng)常使用 XML 在應(yīng)用程序之間交換結(jié)構(gòu)化和半結(jié)構(gòu)化的數(shù)據(jù)。XML 及其相關(guān)技術(shù) — 文檔對(duì)象模型(Document Object Model,DOM)、XPath、HTTP、XQuery 和可擴(kuò)展樣式表語(yǔ)言轉(zhuǎn)換(Extensible Stylesheet Language Transformations,XSLT) — 為快速應(yīng)用程序開(kāi)發(fā)提供了一個(gè)強(qiáng)大的環(huán)境。構(gòu)建在這些技術(shù)之上的應(yīng)用程序?qū)⒄加酶〉膬?nèi)存空間,需要更低的維護(hù)成本,同時(shí)又擁有更高的品質(zhì)和靈活性。
DB2 和其他關(guān)系數(shù)據(jù)庫(kù)的 XML 方面的特性已經(jīng)相當(dāng)成熟,因此除了存儲(chǔ)和管理關(guān)系數(shù)據(jù)之外,它們還是存儲(chǔ)和管理 XML 數(shù)據(jù)的理想選擇。DB2 9 XML 支持(稱為 pureXML)提供了以純 XML 的形式(換句話說(shuō),就是帶注釋的、樹(shù)型的分層存儲(chǔ))存儲(chǔ) XML 的能力。在 DB2 9 中,XML 數(shù)據(jù)可以用 XML 模式索引,可以從關(guān)系數(shù)據(jù)組合而成,可以分解為關(guān)系數(shù)據(jù),可以查詢和轉(zhuǎn)換,可以獨(dú)立發(fā)布,或者通過(guò)混合使用 SQL/XML 和 XQuery 與關(guān)系數(shù)據(jù)組合起來(lái)。
Web 瀏覽器也正在為客戶機(jī)腳本提供更多的功能來(lái)有效地處理 XML。通過(guò)使用異步 JavaScript 和 XML(Asynchronous JavaScript and XML,Ajax),Web 頁(yè)面現(xiàn)在可以直接對(duì)應(yīng)用服務(wù)器進(jìn)行遠(yuǎn)程過(guò)程調(diào)用,并且可以在任何返回的 XML 數(shù)據(jù)上使用 DOM API。
本文將展示如何利用 DB2 XML、Ajax 和 PHP Hypertext Preprocessor (PHP) 提供的功能來(lái)編寫(xiě)簡(jiǎn)單的基于 XML 的應(yīng)用程序。通過(guò)示例場(chǎng)景的幫助,您將學(xué)習(xí)如何在 JavaScript 中調(diào)用 PHP 應(yīng)用程序;如何使用 DOM 和 SimpleXML API 修改 XML 數(shù)據(jù);如何將 XML 從客戶機(jī)傳送到應(yīng)用程序再到數(shù)據(jù)庫(kù);以及如何創(chuàng)建 PHP Web 服務(wù)來(lái)使用 SQL/XML 和 XQuery 發(fā)布關(guān)于 XML 數(shù)據(jù)的報(bào)告。
XML 優(yōu)點(diǎn)
大多數(shù)應(yīng)用程序都用于創(chuàng)建、存儲(chǔ)、操縱和呈現(xiàn)業(yè)務(wù)數(shù)據(jù)。對(duì)象包裝是指將業(yè)務(wù)數(shù)據(jù)綁在一起,使業(yè)務(wù)邏輯更容易處理它們。這些包裝器對(duì)象的很多功能都是根據(jù)關(guān)系和格式化規(guī)則來(lái)提供業(yè)務(wù)數(shù)據(jù)的結(jié)構(gòu),并使業(yè)務(wù)邏輯能夠操縱、發(fā)布和串行化封裝的數(shù)據(jù)。
圖 1. 基于對(duì)象包裝器的應(yīng)用程序
圖 1 闡釋了使用對(duì)象包裝器的一個(gè)示例人壽保險(xiǎn)應(yīng)用程序。每個(gè)方框表示一個(gè)對(duì)象,每個(gè)對(duì)象至少有:
·一個(gè)構(gòu)造函數(shù)
·Getter 和 Setter 方法
·驗(yàn)證代碼
·內(nèi)部對(duì)象層次的串行化
這些對(duì)象與實(shí)際的業(yè)務(wù)邏輯沒(méi)有關(guān)系。對(duì)象包裝是為了使業(yè)務(wù)邏輯更容易管理業(yè)務(wù)數(shù)據(jù)。包裝數(shù)據(jù)所需的代碼比業(yè)務(wù)邏輯要多得多。更多的代碼將導(dǎo)致更多的 bug、更大的固定性、更多的維護(hù)和更高的成本。
如果對(duì)象中的數(shù)據(jù)變量可以格式化為 XML 結(jié)構(gòu),并且對(duì)象的主要作用是將這些數(shù)據(jù)暴露給業(yè)務(wù)邏輯并讓業(yè)務(wù)邏輯操縱它們,那么可以用 DOM 代替對(duì)象。
圖 2. 基于 XML 的應(yīng)用程序
圖 2 展示了一個(gè)使用 XML 和 DOM 包裝器的示例保險(xiǎn)應(yīng)用程序。圖 1 中的所有數(shù)據(jù)包裝器對(duì)象都用一個(gè) DOM 對(duì)象代替。業(yè)務(wù)數(shù)據(jù)是用 XML 建模的,DOM 提供了必要的 API 來(lái):
·創(chuàng)建新的 XML 對(duì)象。
·更新 XML 對(duì)象的值。
·導(dǎo)航 XML 對(duì)象。
·使用 XPath 在對(duì)象層次中搜索。
·串行化和反串行化 XML 對(duì)象層次(換句話說(shuō),就是內(nèi)建持久性)。
通過(guò)使用 XML,可以避免使用大多數(shù)用于管理業(yè)務(wù)數(shù)據(jù)的包裝器對(duì)象。應(yīng)用程序?qū)⒆兊酶雍?jiǎn)潔,并且更多地將重點(diǎn)放在業(yè)務(wù)邏輯上,而不是數(shù)據(jù)管理上。
XML 和架構(gòu)
將 XML 引入架構(gòu)中可以為表示業(yè)務(wù)數(shù)據(jù)帶來(lái)一種標(biāo)準(zhǔn)化的方式。XML 可以提供數(shù)據(jù)的結(jié)構(gòu);XML 模式施加結(jié)構(gòu)和格式化規(guī)則;DOM API 和 XQuery、XPath 及 XSLT 之類的語(yǔ)言使業(yè)務(wù)邏輯可以有效地操縱、發(fā)布和串行化數(shù)據(jù)。由于業(yè)務(wù)數(shù)據(jù)的 XML 表示在客戶機(jī)、中間層和數(shù)據(jù)庫(kù)中都是一致的,因此操縱這些對(duì)象的代碼也是類似的。
我將展示如何在三層環(huán)境中構(gòu)建基于 XML 的應(yīng)用程序,這個(gè)三層環(huán)境由以下幾個(gè)部分組成:
·Web 客戶機(jī):Asynchronous JavaScript and XML (Ajax),DOM
·應(yīng)用服務(wù)器:PHP 和 SimpleXML
·數(shù)據(jù)庫(kù): DB2 9 和 SQL/XML,XQuery
基于 ACORD 人壽數(shù)據(jù)模型的場(chǎng)景
我們來(lái)考慮一個(gè)簡(jiǎn)單的人壽保險(xiǎn)場(chǎng)景,在這個(gè)場(chǎng)景中,首先創(chuàng)建一個(gè)表示新保單的 XML 文檔,然后查詢和操縱這個(gè)文檔,另外還將這個(gè)文檔從一層移動(dòng)到另一層。這個(gè)文檔基于合作運(yùn)營(yíng)研究與發(fā)展協(xié)會(huì)(Association for Cooperative Operations Research & Development,ACORD)用于人壽保險(xiǎn)規(guī)范的 XML,它定義了健康保險(xiǎn)和年金保險(xiǎn)需要交換的數(shù)據(jù)。
為了申請(qǐng)一個(gè)新的保險(xiǎn),客戶需要提供一些基本信息。部分信息是在一個(gè) PHP 應(yīng)用程序中填寫(xiě)的,還有一部分是在客戶機(jī)瀏覽器中填寫(xiě)的。然后,保單存儲(chǔ)在一個(gè) DB2 XML 列中。在 DB2 9 中,XML 類型的列在內(nèi)部將 XML 數(shù)據(jù)存儲(chǔ)為一棵解析后的樹(shù),與關(guān)系數(shù)據(jù)存儲(chǔ)在不同的地方。這種方法是 DB2 9 特有的,更早的 DB2 版本則使用關(guān)系存儲(chǔ)基礎(chǔ)設(shè)施來(lái)存儲(chǔ) XML。
下面是保單 XML 文檔在客戶機(jī)與應(yīng)用程序之間的流程:
·在 Web 客戶機(jī)中,客戶更新頁(yè)面并單擊 Submit。
·Web 客戶機(jī)向 PHP 發(fā)出一個(gè) XMLHTTP 請(qǐng)求,以獲得新的空白保單文檔。
·PHP 應(yīng)用程序打開(kāi)一個(gè)空白的保單文檔,用一個(gè)全局惟一標(biāo)識(shí)符(GUID)更新它,然后將該文檔返回給 Web 客戶機(jī)。
·Web 客戶機(jī)使用 Ajax 捕捉返回的事件,并檢索 XML DOM,然后用 Web 頁(yè)面中輸入的信息填充該文檔。
·Web 客戶機(jī)使用 XMLHTTP 將更新后的 XML 發(fā)送給 PHP 應(yīng)用程序。
圖 3. 創(chuàng)建新的保單請(qǐng)求的 Web 站點(diǎn)。
圖 3 展示了用于創(chuàng)建新的保單請(qǐng)求的 Web 頁(yè)面。當(dāng)用戶單擊 Submit 按鈕后,JavaScript 函數(shù) submitPolicy() 被調(diào)用(見(jiàn)清單 1)。該函數(shù)向 PHP 應(yīng)用程序 createNewPolicy.php 發(fā)出一個(gè) HTTP 請(qǐng)求,以獲得一個(gè)空白的保單。它還設(shè)置一個(gè)回調(diào)函數(shù) fillPolicy(),用于捕捉從 HTTP 請(qǐng)求返回的事件。
當(dāng)?shù)谝粋€(gè)請(qǐng)求到達(dá)中間層的 PHP 應(yīng)用服務(wù)器時(shí),一個(gè)新的 XML 保單文檔被裝載到 SimpleXML 對(duì)象中。通過(guò)使用 SimpleXML API,用 PHP 應(yīng)用程序中創(chuàng)建的 GUID 更新 TransRefGUID 元素。
header('Content-type: text/xml');
$fileContents = file_get_contents("$basedir/acord.xml");
$dom = simplexml_load_string($fileContents);
$dom->TXLifeRequest->TransRefGUID=$guid;
echo $dom->asXML();
然后,這個(gè)文檔被發(fā)送到客戶機(jī)。
對(duì)于本文,我們假設(shè) GUID 是通過(guò)某種機(jī)制(例如時(shí)間和隨機(jī)數(shù)的組合)創(chuàng)建的。更重要的是理解如何將表示保單的 XML 文檔視作內(nèi)存中的業(yè)務(wù)對(duì)象層次結(jié)構(gòu),以及如何使用 SimpleXML API (或 DOM/XPath)來(lái)導(dǎo)航和更新這個(gè)對(duì)象。
填充基本客戶信息
在 Web 客戶機(jī)中,fillPolicy() 函數(shù)讀取返回的值。現(xiàn)在,包含返回 XML 的內(nèi)存中表示的 DOM 對(duì)象可用于操縱保單文檔。客戶在 Web 頁(yè)面上輸入的信息被直接用于更新 DOM。當(dāng)使用客戶信息更新了保單之后,使用 XMLHTTP 將修改后的 DOM 對(duì)象提交回 PHP 應(yīng)用程序(見(jiàn)清單 2)。即使是 HTML 組件值也是用 DHTMLDocument Object Model (DOM) 讀取的。