程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java與.NET的SOA互操作簡易教程

Java與.NET的SOA互操作簡易教程

編輯:關於JAVA

在本文中,我們打算展示一下如何使用簡單的技術加上以文檔為中心的方式 帶來有價值的業務服務,而無須使用專有的中間件,也不必引入Web服務棧的復 雜性。我們的靈感來自於REST的架構風格,以及把XML移到HTTP協議之上的能力 。

Web服務的方式

介紹我們這個方式的最好辦法就是將它和一個簡單的Web服務例子相對比。假 設有一個簡單的天氣服務,暴露出一個名為“WeatherQuery”的Web方法,這個 方法返回一個對象,包含溫度和氣壓值。在通常情況下,人們拿現成代碼,使用 工具來暴露方法,並生成WSDL。

如果你相信這個騙局,那麼要做的無非就是找到一個WSDL在Java下的等價工 具,然後生成存根(Stub)代碼。

不巧的是,事情並沒有那麼簡單,WSDL是一個概括性的標准,而且實際上范 圍到可以讓人自由诠釋。在我們的例子裡,我們發現.NET強制使用基於文檔的方 法,而Java工具則采用了相反的RPC方法。此外,我們還發現以下方面存在問題 :命名空間混淆,Schema的包含,以及工具將WSDL切分成若干獨立部分。簡而言 之,這項技術已經開始把注意力放在我們試圖解決的實際問題之外了。

除了這些問題,我們還發現Web服務的工具之間存在不一致性。例如,對於自 動發布的WSDL文檔,不同版本的Internet Information Server和Web Services Enhancements之間,還有它們的Java等價產品,彼此之間只能部分兼容。

有些東西今天七拼八湊起來可以工作,但到了明天,如果服務的後續版本需 要更復雜的Web方法時就得拋錨。這些東西真是令我們倍感厭煩。

更RESTful的風格

上面的方法裡存在兩個關鍵性假設:首先,僅暴露一個已有方法調用就足以 給我們帶來一個有意義的服務;其次,使用工具能使通過Web服務訪問到這個服 務的工作變成小菜一碟。

我們可以把請求看做一個包含請求的類型還有相應參數的文檔,而不是考慮 請求的參數和返回的類型。把這個文檔當成對試圖建模的業務過程中契約的一部 分的描述。如果我們以相同的WeatherQuery方法為例,用常見的XML來描述它, 那麼就可以得到類似下面的東西——

同樣,作為文檔,返回類型看起來會像這樣——

現在我們可以定義一個簡單的類,用於表示文檔中的相同字段——

關於這兩個文檔,有意思的是它們在.NET和Java中都比較容易序列化和反序 列化。對於.NET來說,內建的XML序列化機制(帶標注/Annotations)可以很輕 松地完成這項工作。對於同樣一個類,C#代碼如下:

Java開發人員就沒那麼幸運了,因為Java並不提供內建的XML序列化工具:不 過有一個名為XStream的開源項目(http://xstream.codehaus.org),能幫我們 完美地完成這項工作:

我們的Weather服務目前僅需負責文檔的交換,而作為結果,我們就可以使用 簡單的HTTP而不用使用Web服務了。

有了這樣的轉變,我們就可以考慮讓多個文件類型使用同一個進入系統的入 口點,從而為我們帶來一個更可擴展的方法。

編寫Java服務器的代碼

用於此服務Java實現的技術包括XStream序列化類庫,以及任意一個Servlet 容器,因為我們選擇用Servlet提供這些服務。XStream類庫的源碼是開放的,而 Servlet容器可以是WebLogic、WebSphere、JBoss、Geronimo或者Orion。如果對 J2EE中的E(企業特性)要求沒有那麼高,那麼甚至只用Resin、Tomcat或者 Jetty就可以了。

我們的Servlet應當實現doPost()方法,而不是doGet()方法。對於XML,我 們沒有使用名稱/鍵值對:我們僅僅使用完整的POST內容主體,這有點超出HTTP 規范涵蓋的范圍了。不過,這只是個人喜好的問題——只要在服務器端和客戶端 相同就可以了。

在請求傳入時,我們使用XStream將XML反序列化成一個命令對象,然後合 理地進行處理就可以了。

編寫.NET服務器的代碼

用於.NET服務器端的代碼要簡單得多——我們僅需使用Internet Information Server(IIS)和.NET的內建XML序列化機制就可以了。內建的序列 化機制要求C#屬性將字段標記成XML元素而不是XML屬性。當然,還存在著 XStream的一個.NET移植版本,不過我們還沒有拿它做過實驗,而我們也聽說過 開源社區還將有另外一個移植版本發布。

編寫Java客戶端的代碼

對於Java客戶端,除了XStream以外,我們還得使用Apache的HttpClient類庫 (以及相應的依賴類庫)。

請參見http://jakarta.apache.org/commons/httpclient。

HttpClient類庫用起來很簡單,並且允許POST操作在執行之前被以編程的方 式創建。記住,POST內容主體完全是用XStream生成的XML,形式可以是名稱/鍵 值對,或者是除去HTTP構造的完整請求。如果你希望為服務創建一個測試Web表 單,那麼前者可能更有吸引力一些。

編寫.NET客戶端的代碼

對於.NET客戶端,只要有.NET框架就沒問題了,不管是1.1或者2.0都可以。

對於POST操作,可以使用內建的WebRequest類和內建的序列化機制。

提升服務的可擴展性和兼容性

簡單POST表達命令的XML的好處在於,我們可以在稍後加入更多的命令,而不 需要改變我們的消息實現方式。服務器可以在運行期決定是否可以處理相應的 XML:

要處理今後可能出現的多種類型,好的解決方案是為每個類型注冊一個處理 器,如此一來就可以避免大量的if/else或者switch/case代碼塊了:

在使用XML是,人們面臨著過分依賴於相關Schema的誘惑,我們必須仔細了解 Schema驗證和客戶實際所需信息之間的差別。

如果Schema驗證在運行期執行,會帶給開發人員不恰當的安全感。錯誤仍然 可能發生——可能錯誤的XML還是會被發出。但這時候出現了什麼?答案是會有 一個Schema無效的異常信息被拋出。使用把XML映射到類定義的方法,可能存在 兩種情況:要麼得到一個正確的對象,要麼該對象會丟失某些字段。在這種情況 下,可以拋出一個帶有真實原因的真正異常,它可以很容易地被轉換回一條清晰 的XML回復信息提供給客戶。關鍵的區別在於,異常只在必要信息缺失的情況下 拋出——其它東西都可以有變更。

這種設計所固有的可能性在於,XML中可以加入新的元素(對應於類中的字段 ),從而使得讓API在表義性上更上一層樓成為可能。經過仔細的測試之後,服 務將可以支持客戶發送舊版本的請求文檔。一般意義上的API變更,以及“額外 字段”級別上的變更,也會變得更加意義深遠:

不過,要是把版本號也加入URL就更好了: http://x.com/weather/WeatherQuery/2.0

以Web服務的形式包裝服務

如果你要在同一台服務器上放上另外一個服務,用於使剛才的服務處理標准 的Web服務請求,那麼沒有什麼可以阻止你這樣去做。你所需要的,不過是WSDL 指定的方法而已,就像這樣:

在工具上的選擇,包括:.NET平台下的WSE 2.0/3.0,Java平台下是Glue、 AXIS、JAX-WS或者J2EE容器內建的適配器。進行SOAP編碼的方法可以簡單交給為 純REST實現開發的反序列化-執行-序列化的代碼來完成。這樣一來,你就可以避 免負責公司標准監控的人來找麻煩了。

將服務擴展至消息傳送(Messaging)

在使用了TIBCO Rendezvous 之後,我們就可以將請求的相同XML表現形式發送到隱式的異步服務執行了。我 們還沒有嘗試過MQ系列,不過應該沒有什麼問題。

就我們的范例來說, 這意味著針對天氣詳情的請求不會馬上得到回復。相反,在等待片刻之後才會收 到響應。這是一個巨大的變化,可能意味著你不得不改變或者放棄對API的某些 簡單設計。例如,下面的Façade方法可能派不上用場了:

取而代之的是兩個接口,每一個都帶了單獨的方法,這樣會更合適些 :

關於消息傳送的模式,有許多值得學習,不過在這裡我們不打算深入 探討。然而,值得一提的是,存在兩個常用的模式值得我們考慮一下。第一種設 計是隊列,在這個設計中,你發送的請求只能接受返回給你的請求。第二種概念 是多播(Multicast),其中線上的事件被發送到多個訂閱者處(出版者/訂閱者 模式)。此外,一個沒有明確指出的事實,你可以設計出一個隊列,讓它持續不 斷地發送修正的信息。如果你熟悉JMS的話,那麼Rendezvous在這方面和它只有 些許不同。

WSDL到哪兒去了?

我們編碼完成的生產者/消費者設計以簡單的形 式交換XML。但是,在正式的Web服務設計中發現階段所固有的協議檢查在我們這 個例子裡是不存在的。

對此,我們的建議是,這並不是必要的。相反, 全面遵循敏捷思維,設計出一套全面符合持續集成(Continuous Integration) 的集成測試。這樣,在部署上線之前,服務的不兼容問題就可以事先發現。因此 ,你可以把一套復雜的WSDL規范丟在一旁,取而代之擁有的是一系列從提供者和 使用者角度斷言描述服務的單元測試。不管怎麼說,WSDL只能在運行期提示不兼 容問題,而這時候恢復已經不是一件容易的事情了。這麼說來,我們是不是錯為 它建了神龛了?

要以平台無關的方式創建這類測試,Schematron是可選 方案之一。

要輔助調試和文檔,你還得准備一些范例文檔:

此外,你還可以使用XML Schema(XSD)來控制文檔格式:

同時靜態提供XSD和范例XML是個不錯的注意(碰巧作者們在XSD方面意 見不統一)。在這裡“靜態提供”指的是,API可以由人們通過Web浏 覽器手動請求調用 ——

http://x.com/weather/xsd/WeatherQuer

http:/ /x.com/weather/sample/WeatherQuery

記住,XSD和范例文檔都只是可選方案,也可以很容易地生成。

本文要點回溯

本例中的法寶是使用Codehaus的XStream,通過HTTP-POST而不是GET與.NET進 行文檔交換。其它的所有內容早就有人在博客上撰文詳述或者寫過相應白皮書了 。選用XStream意味著消息本身的“規范”存在與Java和/或C#的代碼當中,而不 存在於基於XML、常常讓你不得不面對WS-*規范的設計中。

此外,傳統的REST金科玉律推薦使用HTTP-GET,因為它更適合對命令進行編 碼……

http://x.com/weather/WeatherQuery?locn=Chicago

……在結果可以被Web服務器緩存的情況下尤其如此。或許我們這種風格最適 用於通訊的場景,在這種情況下,試圖進行緩存是沒有意義的。在GET方案中存 在著另外一些優勢,這些優勢是我們的方案所不具備的。GET方案更優雅,並且 在可測試性上更突出,人們可以使用浏覽器通過完整的URL完成測試。然而,它 所或缺的,是POST方法所帶來多功能性,對於參數格式上不僅局限於名稱/鍵值 對;而且XML的有效載荷的復雜程度也可以任意指定。當然,在更大型的解決方 案中,GET和POST都擁有一席之地。

在這篇論文撰寫過程中,我們向XStream團隊提了一項建議(用補丁的形式) ,讓XStream在合適的地方對屬性的支持更加游刃有余。XStream開發團隊實現了 必要的功能,而XStream今後的版本將可以支持XML屬性,以便與.NET實現更加無 縫的互操作。

我們還提到,這個方法對於異步傳輸,如Tibco RV,也同樣適用。在這方面 ,目前WS-*規范的工具基本上沒有提供支持。

在文章末尾,我們不能肯定這是否是POST-REST(PREST),或者只是傳統的 REST,不帶緩存和URL簡化功能,也沒有新造的名詞。

查看英文原文:

Simple Java and .NET SOA interoperability

http://www.infoq.com/articles/REST-INTEROP

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved