級別: 中級
Nicholas Chase
(ibmquestions@nicholaschase.com), 顧問, Backstop Media
2006 年 11 月 05 日
面向服務的體系結構(Service-Oriented Architectures,SOA)當前強調的重點在 Web 服務上,但很容易被所傳播的各種信息搞得昏頭轉向。本系列教程將對主要 Web 服務規范進行全面說明,從簡單對象訪問協議(Simple Object Access Protocol,SOAP)一直介紹到 WS Business Process Execution Language (WS-BPEL)。本教程是系列教程的第 3 部分,將說明統一描述、發現和集成 (UDDI) 的基本概念,并介紹如何使用 Java 應用程序訪問它。
開始之前
本教程介紹統一描述、發現和集成 (UDDI)。UDDI 指定 Web 服務和其他公司信息的注冊中心,旨在提供一種發現可使用的新 Web 服務并在理想的情況下實現操作自動化的方法。
本教程假定您熟悉 Web 服務和 SOAP 的一般概念。熟悉 WSDL 的相關知識也將有所幫助,但本教程中會對一般概念進行回顧。
為了理解本教程最后一部分給出的代碼,您需要熟悉 Java,不過其中的概念與本教程的其他內容一樣,適用于任何編程語言。
本系列教程以假想的報社 Daily Moon 為例,為了提高在競爭激烈的環境中的工作效率,其員工將使用各種 Web 服務來創建工作流系統,我們將在此過程中講解各個 Web 服務基本概念。
第 1 部分說明了 Web 服務背后的基本概念,并演示了如何使用 SOAP(后續教程討論的大部分內容的基礎規范)來將 Classifieds Department 連接到內容管理系統。
第 2 部分進一步深入說明如何使用 Web 服務描述語言 (WSDL) 定義 Web 服務預期產生的消息,從而使團隊更方便地創建服務以及連接到服務的客戶機。
在第 3 部分中,團隊希望準備一系列服務,并希望能方便地查找這些服務。與此對應,統一描述、發現和集成(Universal Description, Discovery and Integration,UDDI)提供了可用服務的可搜索注冊中心,以便使自己的服務為其他人所注意。
第 4 部分和第 5 部分討論 WS-Security 和 WS-Policy,將詳細說明如何保證該報社的服務的安全,以及團隊為了訪問這些剛提供了安全保護的服務需要進行哪些更改。
第 6 部分重點討論互操作性,因為必須從單個系統訪問來自幾個不同實現的服務。這一部分還將討論 WS-I 證書中涉及的要求和測試。
最后,第 7 部分演示如何使用業務流程執行語言(Business Process Execution Language,WS-BPEL)來從各個服務創建復雜應用程序。
接下來讓我們更為詳細地了解一下本教程中將討論的內容。
![]() ![]() |
![]()
|
本系列的第 1 部分 介紹了 Web 服務,并強調了 SOAP 的重要性。這些內容是通過虛構的 Daily Moon 報社的 Classifieds Department 進行相關工作的過程說明的。在本系列的第 2 部分中,Classifieds Department 決定創建自己的服務,并使用 Web 服務描述語言 (WSDL) 記錄其使用方式。在第 3 部分中,報社的發行人決定全面推行 Web 服務,并強制要求使用 UDDI 注冊中心來記錄所有可用服務。
在本教程中,您將了解以下內容:
- 什么是 UDDI
- UDDI 的用途
- UDDI 數據的結構
- 如何有效地使用 UDDI 表示 WSDL
- 可以對 UDDI 數據執行的操作
- 使用 Java 與 UDDI 注冊表交互
![]() ![]() |
![]()
|
為了處理本教程中的代碼,您需要有以下軟件:
Apache Geronimo 或其他 UDDI 實現。為了處理本教程中的代碼,您需要訪問 UDDI 注冊中心。為了實現此目標,所使用的注冊中心類型并不重要,因為 UDDI 根本就是 Web 服務,應該可以從任何平臺或語言進行訪問,并能夠訪問任何平臺或語言。既然這樣,就可以使用我們在本系列的第 1 部分和第 2 部分使用的 Apache Geronimo 應用服務器(同時也是 IBM 的 WebSphere Community Edition 的基礎),其中預安裝了 Apache 的 UDDI 注冊中心實現 jUDDI,并將其配置為基本安裝的一部分。您可以從 Apache.org 下載 Apache Geronimo。有關安裝 Geronimo 的更多信息,請參見本系列的第 1 部分。
UDDI4J——為了訪問注冊中心,本教程說明了 UDDI4J 項目的使用方法;此項目提供了 UDDI 概念和 Java 代碼間非常緊密的集成。可以從 Sourceforge.net 下載 UDDI4J。
Apache Axis2 或其他 SOAP 實現——可以手動創建 SOAP 消息,也可以手動對其進行解釋,但手邊如果有一個可用實現就會方便得多。您將使用的是 Apache Axis2,其中包含了各種 SOAP 相關的 API,可極大地簡化您的工作。可以從 Apache.org 下載 Apache Axis2 。本教程使用的是 0.94 版,但應該也能使用更高版本。
Java 2 Standard Edition 的 1.4.x 版——所有這些工具都是基于 Java 的,本教程中將要構建的服務和客戶機也是如此。可以從 Sun Developer Network 下載 J2SE SDK。Geronimo 將無法與 Java 1.5 一起正常使用。
另外,還需要 Web 瀏覽器和文本編輯器,但我想您已經有了這兩個工具。如果愿意,還可以使用 Eclipse 之類的 IDE,但由于我們的重點是技術而不是工具,因此我將使用文本編輯器和命令行來編輯和編譯文件。
![]() ![]() |
![]()
|
概述
讓我們看一看目前已經完成的工作。
本系列教程逐步說明了虛構的 Daily Moon 報社的員工將其日常操作更改為基于 Web 服務的系統的過程。在第 1 部分中,Classifieds Department 通過與內容管理系統交互了解了 SOAP 的相關信息,在第 2 部分中,他們創建了自己的服務,并使用 Web 服務描述語言 (WSDL) 對其進行描述。現在,該報社的發行人 Rudy 對 Web 服務在其組織內的工作情況印象非常好,希望能更廣泛地應用 Web 服務,甚至希望將其用于與其他組織進行交互。
為此,他要求 IT 人員 Gene 和 Francis 創建一個 Web 服務注冊中心,以便能讓其他部門更方便地找到為了將自己的操作過渡到 Web 服務而需要的構件。
Gene 和 Francis 認為最好的做法是實現統一描述、發現和集成 (UDDI) 注冊中心,從而不僅能存儲有關報社自己服務的信息,還能夠與其他報社的注冊中心進行交互。
![]() ![]() |
![]()
|
向 UDDI 注冊中心注冊服務的部分過程將涉及到對 WSDL 定義進行操作,因此在開始新項目前,Gene 重新分析了一下上個項目中的文件,以回顧 WSDL 的基本概念。請參見清單 1。
清單 1. WSDL 文件
<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://www.daily-moon.com/classifieds" xmlns:ns1="http://org.apache.axis2/xsd" targetNamespace="http://www.daily-moon.com/classifieds"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://org.apache.axis2/xsd" elementFormDefault="unqualified" attributeFormDefault="unqualified"> <xs:element name="createNewAdRequest"> <xs:complexType> <xs:sequence> <xs:element type="xs:string" name="content" /> <xs:element type="xs:string" name="endDate" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="createNewAdResponse"> <xs:complexType> <xs:sequence> <xs:element type="xs:int" name="newAdId" /> </xs:sequence> </xs:complexType> </xs:element> ... </xs:schema> </wsdl:types> <wsdl:message name="createNewAdRequestMessage"> <wsdl:part name="part1" element="ns1:createNewAdRequest" /> </wsdl:message> <wsdl:message name="createNewAdResponseMessage"> <wsdl:part name="part1" element="ns1:createNewAdResponse" /> </wsdl:message> <wsdl:message name="getExistingAdsResponseMessage"> ... </wsdl:message> <wsdl:portType name="ClassifiedServicePortType"> <wsdl:operation name="createNewAd"> <wsdl:input message="tns:createNewAdRequestMessage" /> <wsdl:output message="tns:createNewAdResponseMessage" /> </wsdl:operation> <wsdl:operation name="finalizeIssue">...</wsdl:operation> <wsdl:operation name="editExistingAd">...</wsdl:operation> <wsdl:operation name="getExistingAds">...</wsdl:operation> </wsdl:portType> <wsdl:binding name="ClassifiedServiceBinding" type="tns:ClassifiedServicePortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <wsdl:operation name="createNewAd"> <soap:operation soapAction="createNewAd" style="document" /> <wsdl:input> <soap:body use="literal" namespace="http://ws.apache.org/axis2" /> </wsdl:input> <wsdl:output> <soap:body use="literal" namespace="http://ws.apache.org/axis2" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="finalizeIssue">...</wsdl:operation> <wsdl:operation name="editExistingAd">...</wsdl:operation> <wsdl:operation name="getExistingAds">...</wsdl:operation> </wsdl:binding> <wsdl:service name="ClassifiedService"> <wsdl:port name="ClassifiedServicePort" binding="tns:ClassifiedServiceBinding"> <soap:address location= "http://www.daily-moon.com:8080/axis2/services/ClassifiedService" /> </wsdl:port> </wsdl:service> </wsdl:definitions> |
由于篇幅的原因,我們從此文檔中刪除了部分代碼,但我們仍然能通過剩下的部分了解其一般概念。
首先看最下面,我們定義了實際的服務,可通過特定的位置對其進行訪問,且實現了 ClassifiedServiceBinding
接口。該接口表示為綁定,指定在 ClassifiedServicePortType
portType 中定義的操作。portType
使用在 types 部分中定義的元素定義輸入和輸出消息。
XML 客戶機可以讀取此信息,并將其用于訪問 Web 服務。(或者,更為準確地說,Web 服務客戶機生成工具可以讀取此信息,然后生成可以訪問 Web 服務的客戶機。)
![]() ![]() |
![]()
|
在本教程中,Gene 和 Francis 將 Daily Moon 的信息拆分為 UDDI 友好的結構,包括業務信息和服務信息。他們將使用其通過 UDDI4J 將報社的信息和服務輸入 UDDI 注冊中心。它們還將與另一個報社 Daily Star 的私有注冊中心協同工作,以查找提供即時體育賽事比分的服務。
現在讓我們看一看到底什么是 UDDI。
![]() ![]() |
![]()
|
UDDI 簡介
UDDI 基本上就是一個 Web 服務,但與 SOAP 和 WSDL 存在很大差異,最好在開始之前了解一些背景知識。
當所有應用程序都位于本地時,要找到所需的功能會非常容易。不過,使用 Web 服務之類的分布式系統時,您不能獲得中央注冊中心的好處。分布式系統也容易發生更改。而這正是 UDDI 的用武之地。它旨在用于兩個目的。最初形成時,它被認為是一種“通用業務注冊中心”。其想法是,企業可以使用以下三種方法之一搜索合作伙伴:
- “白頁”:白頁與電話簿中用于查找公司信息的白頁類似。例如,如果您知道公司的名稱,可以在其中查找公司的地址、如何進行聯系,甚至還能夠確定與組織中的哪個人聯系。
- “黃頁”:同樣,黃頁與電話簿中的黃頁一樣,可以在其中根據分類查找公司。UDDI 指定了各種分類法,以供各個公司用于對自己進行分類。例如,如果您在查找體育用具,則可以查找其北美工業分類系統(North American Industry Classification System,NAICS)代碼為 339920 的公司。
- “綠頁”:電話簿中沒有綠頁,但這里的想法是,公司可以使用此搜索方法來查找實現了特定服務的貿易合作伙伴。例如,可以搜索實現了使用郵政編碼的距離計算功能的公司。
UDDI 同時也被認為是一種保持分布式應用程序長期運行的方法。其想法是這樣的,可以緩存有關訪問特定服務的信息,如果客戶機崩潰,應用程序將自動回到注冊中心并進行檢查,以確定信息是否已更改。如果已更改,則可以直接在應用程序內進行更改(在理想的情況下將自動進行更改)并重試您的請求。
![]() ![]() |
![]()
|
當 Francis 想嘗試統一業務注冊中心(Universal Business Registry,UBR)時,發現它已不復存在了。事實上,在推出 UDDI 3.0 版時,UBR 已被其企業贊助商終止了。為什么呢?無論 UBR 的想法多么好,但事實是基本上沒有人使用它。其原因是雙方面的:首先,在 UBR 中幾乎沒有任何可用信息——除非希望使用的是實時股票行情服務(在此情況下可找到大量信息)。第二個原因是,通常公司并不會與不熟悉的組織開展業務。很少有組織通過自動搜索尋找貿易伙伴,然后在不進行大量前期工作的情況下直接向其開發系統。自動搜索和調用模型并沒有實際的效用。
同時,這也受到 UDDI 在某種意義上有些超前的事實的阻礙。它設計為處理所有類型的服務,而不僅是 SOAP over HTTP,并沒有提供使用 WSDL 定義的機制(至少嘗試使用它的人這樣認為)。
不過,這并不是說根本不會使用 UDDI。相反,實際上它更多地用作“私有注冊中心”。各個公司創建自己的注冊中心,并在其中輸入自己的服務。UDDI 還可以用作內部的業務注冊中心,就像 LDAP 的傳統用法一樣。
而且,隨著從“只有 Web 服務”的思維方式轉變為更多強調面向服務的體系結構(Service Oriented Architecture,SOA)的思維方式,這種處理 SOAP 之外的內容的能力可能具有極高的長期價值。
![]() ![]() |
![]()
|
UDDI 注冊中心中的信息包含五種不同類型:
-
businessEntity
或實際企業組織。這可以是整個組織,也可以為隸屬部門或分支機構。 -
publisherAssertion
或各個businessEntities
間的關系。publisherAssertions
必須由雙方共同聲明才有效(因此無法將自己聲明為另一個公司的分支機構),除非兩個實體都對發布者負責,或除非兩個實體都由同一個用戶帳戶輸入注冊中心。 -
bindingTemplate
,這對服務接口的規范非常重要。它可以由多個businessServices
進行實現。 -
businessService
或業務提供的服務。雖然現在看起來有些簡單,但在 UDDI 的世界中,這并不意味著它是 Web 服務。例如,可以實際將您的公司的電話服務支持(即用戶實際撥打的電話號碼以及其他相關的內容)指定為 UDDI 服務。當然,您并不會提供虛擬 WSDL 文檔,但這將是您的公司提供的一個服務。 -
tModels
或元數據模型。研究了 UDDI 后,Francis 得出結論,tModel 可能是 UDDI 未達到預期目標的最大原因。作為服務的注冊中心,您希望找到像 WSDL 一樣直接為服務指定接口的方法。但是,正如所指出的,UDDI 并不是僅供用于 Web 服務,而是設計時包含了更大的靈活性。tModels
的確可幫助指向 XML 文檔(我們稍后將證實這一點),但事實上旨在提供通過服務、業務或任何其他對象指定關于某個事項的信息的通用方法。
以上是 UDDI 的基本數據結構。現在讓我們了解一下可以用于與 UDDI 交互的方法。
![]() ![]() |
![]()
|
UDDI 被認為過于復雜,但其核心在于上述五種數據類型以及四個操作:find、get、save 和 delete。也就是說,UDDI 規范說明了可以對數據進行的以下操作:
-
find_xx
:find_businessEntity
、find_businessService
等方法提供了在 UDDI 注冊中心中搜索記錄的方法。這些方法返回用于標識對象的鍵。 -
get_xx
:獲得了標識對象的唯一鍵后,可以使用get_businessService
等get_xx
方法來檢索實際的對象本身。例如,get_businessService
將返回整個businessService
對象,可從其中獲得任何所需的信息。 -
save_xx
:您可能已經猜到,這些方法會將信息添加到數據庫,或更改數據庫中已經存在的信息。 -
delete_xx
:delete_bindingTemplate
、delete_tModel
等方法獲取對象的唯一鍵作為參數,然后將其從數據庫中刪除。這些方法的實際行為根據所刪除的對象不同而有所變化。例如,由于數據庫中的其他對象經常引用tModels
,因此并不能實際將其刪除,而會將其隱藏。
幾乎所有的 UDDI 都依賴于五個對象(businessService
、bindingTemplate
、publisherAssertion
、businessEntity
和 tModel
)與四個操作(find
、get
、save
和 delete
)的這 20 個交叉方法。
現在讓我們看一看此結構的實際情況。
![]() ![]() |
![]()
|