天天看點

消息總線擴充之面向消息的資料內建相關技術簡介基于消息總線實作資料內建

最近一段時間,我在琢磨消息總線除了能進行受管控的消息通信之外,還有哪些可以擴充的方向。這篇文章我們來探讨一下面向消息的資料內建是否可以作為一種嘗試方向。

談到XML我們的第一映像就是用它來做各種配置,當然如果你是Javaer,那麼可能你印象最深的就是Spring的bena配置了。其實,XML的用途遠不止充當配置檔案這一方面。它還被廣泛應用于異構系統內建、資料內建、語義/協定轉換等等方面,甚至成為建構平台非常重要的基石。雖然XML一直以來被人诟病其解析效率低下以及資料量太備援而不夠精簡。但目前除了它沒有一種集平台無關性與良好的可讀性以及嚴謹的限制規範于一體的标準,是以,如果你曾經閱讀過一些架構的源碼的話,你就會深刻了解XML的重要性(如果你了解Apache

Ofbiz的話,會看到他在其架構體系中大量使用了XML)。

XSLT(XSL轉換)即擴充樣式表語言轉換。它是XSL(擴充樣式表語言)的子語言,也是XSL中最重要的部分,它使用XPath在XML進行導航。主要用于将XML轉換為XHTML以及其他形式的XML。一個通俗的比方就是:CSS基于HTML就如同XSL基于XML。W3C在制定XML之初就已經為其格式轉換制定了标準,XSLT包括了程式設計常用的實作方式:條件分支、循環周遊,除此之外還包括模闆封裝,函數封裝,甚至可以執行特定語言實作的函數,可謂非常強大。

通過

XSLT,您可以向或者從輸出檔案添加或移除元素和屬性。您也可重新排列元素,執行測試并決定隐藏或顯示哪個元素,等等。描述轉化過程的一種通常的說法是,XSLT 把

XML 源樹轉換為 XML 結果樹。

Java API for XML Processing(Java

處理XML的API),提供了一些通路以及處理XML相關的技術實作,包括但不僅限于SAX、DOM以及XSLT轉換等。通過JAXP提供的API可以将某個源XML格式基于XSLT轉換成目标格式。

JAXB (Java Architecture for XML Binding) 是一個業界的标準,即是一項可以根據XML

Schema産生Java類的技術。該過程中,JAXB也提供了将XML執行個體文檔反向生成Java對象樹的方法,并能将Java對象樹的内容重新寫到XML執行個體文檔。有多種實作。

通過介紹上面兩個技術,可以知道XML到XML的資料轉換是可行的,但XML通常都不是每個業務系統最終存儲或表示資料的方式(現在最常用的資料存儲方式是資料庫)。我們當然也可以在XML跟資料庫中的資料之間進行轉換,但如果能夠用各個平台的業務對象來作為中間的銜接,就可以在XML跟各異的資料庫之間進行解耦。比如就拿Java而言,常用的做法是:database<->JavaBean(POJO)<->XML。Database跟Java

bean之間交給JDBC,而Java

bean跟XML之間可以交給JAXB或某種基于Java對象跟XML之間進行序列化或反序列化的庫。是以就Java平台而言,我們隻需要通過JAXB實作XML與Java

Bean之間的轉換就可以了。當然對于其他平台(比如dot net),其思路也是一樣的,并且XML在各個平台上都存在非常成熟的序列化與反序列化庫。

《企業內建模式:設計、建構及部署消息傳遞解決方案》一書的消息轉換章節(3.6節)對以上基于XSLT的消息轉換做了介紹,然後在Oracle的服務總線上看到它有提供這一功能,并且所用技術也是XSLT,另外Mule

ESB也支援XSLT來對XML格式的資料進行格式轉換。

服務總線可以進行資料轉換消息總線是否可行?其實,這主要取決于你從什麼角度來看待它們。服務總線基于SOAP以及HTTP協定提供服務的通路。而消息總線提供面向消息的通信機制,從技術層面上來講其實都是提供通信機制。是以,從技術角度上來講是沒有問題的。下面我們來探讨一下通過消息總線如何進行資料格式轉換。

首先,我們認為每個隊列隻處理一種消息格式是一種比較好的實踐,并且我們假設通信雙方的資料表示格式都是XML。然後我們針對每個隊列為其處理的消息(XML資料)定義一個Schema,這樣用于內建的兩個隊列就會存在兩個Schema(消息發送方跟消息接收方)。在跟目标隊列通信之前,消息發送方根據目标隊列的schema,編寫一個适配它的XSLT檔案,這個XSLT你可以簡單地将其看做是針對消息接收方的擴充卡,它會跟目前通信鍊路建立關聯。下面我們來看一下這種需求場景下消息通信的大緻流程:

消息發送方無需針對目标隊列識别的消息格式進行任何處理,它隻需發送自己格式的消息。然後pubsuber伺服器會擷取到目前隊列定義的schema,對消息進行驗證,如果驗證通過,根據發送時指定的鍊路token擷取到目前隊列針對目标隊列的XSLT定義,消息總線用戶端在内部對發送消息基于XSLT進行轉換,即可将待發送的消息在發送端轉換成目标隊列可識别的消息,然後發送出去。在接收端,目标隊列消費者消費的消息就都是适配過的可識别消息,當然消息總線内部會對接受到的消息用其預先定義的schema進行驗證。

流程圖大緻如下:

消息總線擴充之面向消息的資料內建相關技術簡介基于消息總線實作資料內建

消息總線在這裡所起到的作用主要是底層通信支援。這裡對于隊列的schema以及XSLT的擷取得益于消息總線的一個配置&推送中心——pubsuber。消息總線的用戶端在發送端攔截了消息,然後在發送之前根據XSLT對消息進行轉換。

由于篇幅限制,這裡我們暫且假設某個要內建的資料已經由原始資料被轉換成了XML格式表示的資料(這不是技術上的問題,每個語言平台上都存在各種在對象與XML之間進行序列化與反序列化的工具)。現在我們有一個發送端學生資料的Schema:

我們需要與另一個系統進行資料內建,另一個系統的接受隊列定義的處理資料的schema如下:

很明顯,它們之間如果不進行一些必要的資料轉換是無法進行對接的。首先源資料的元素名稱是基于英文定義的,而目标資料的元素名稱基于所謂的國家标準(漢語拼音的首字母縮寫)。另外源資料的出生日期用一個元素來表達,而目标資料将其年月日拆分成三個元素來表達。源資料中提供了“專業”元素,但目标資料中不需要該元素;而目标資料中需要“是否統招”元素,而源資料中沒有該元素。是以我們可以針對另一個系統定義的Schema來編寫一個XSLT對源資料進行适應性轉換。XSLT如下:

而從源資料通過XSLT轉換為目标資料的格式的代碼非常簡單(真實的實作中,這應該在消息總線用戶端内實作,此處隻是展示實作代碼):

得益于XSLT充當擴充卡的角色,這種方式對通信雙方代碼的侵入性極低,幾乎可以說事透明轉換的。其實無論是否是基于消息總線,面向消息的資料內建都是可行的方案。而消息總線給這種內建帶來了更多的便利:比如适合內建方與被內建方的pub/sub的通信模型、pubsuber作為Schema以及XSLT的中繼資料管理中心、受控的通信行為等。

原文釋出時間為:2015-04-05

本文作者:vinoYang