柴曉路 (fennivel@uddi-china.org) Chief System Architect 2001年9月17日
(本文最初由 IBM developerWorks 中國網站發表,其網址是 http://www.ibm.com/developerWorks/cn/)
本文是架構Web服務的系列文章的第五篇,以在前文中描述的應用實例為基礎,詳細定義了Catalog服務的API消息,全部API是使用SOAP完成調用和返回的,本文通過API的具體定義,詳細介紹和演示了交互的數據結構和API消息結構的定義方法和相應模式,為讀者在定義自己的Web服務接口時提供了實例的幫助和教程。
在本系列的前一篇文章中,對于給出的Case做了系統分析,并對系統作了模塊劃分,初步界定有如下在線服務組件:
- Catalog Service - 類別(Category)管理,產品(Product)管理,數據交換,數據備份等;
- Order Service - 接受訂單,向其他接受訂單的服務發送訂單等;
- Feedback Service - 反饋信息(Feedback)管理,數據交換等。
由于這些服務顯然必須有一個用戶系統來支持,無論是因為安全性的考慮(有權限的才能做某些操作,還是因為事務的用戶相關性(顯然Order這樣的服務不大可能脫離用戶而實施)。因此我們需要增加一個在線服務Member Service,Membership的申請基本上可以依靠Web服務之外的流程完成,比如Web Application,因此Member Service的Web Service界面相對可以非常簡化。所有這些在線組件服務需要提供的對外接口,我們的詳細定義從下圖開始:
Figure 1.牋 API消息

本文所引用的資源主要包括兩類,一類是Web服務的技術資源網站,包含了大量Web服務的技術信息,另一類是Web服務“stack"系列技術規范,他們是一個整體的技術體系,包括UDDI、SOAP、WSDL、XML等。本文的最后給出了這些資源的鏈接,有興趣的讀者可以通過這些資源鏈接找到所需的內容。
API概述
對于整個系統的API設計,其遵循的原則有這樣幾條:
-
簡單性,由于這是一個對于公共開放的Web服務,它的API的設計首先應當是簡單的,要被大量用戶接受,要獲得比較好的應用,那么API必須簡單,沒有哪個復雜難用的API會得到大家的廣泛接受的,除非是普及率太廣的系統,而目前我們要設計的Web服務是新系統,所以針對目前的應用實況,API必須簡單。
-
可擴展性,作為更新頻率較高,開放性較強的Web服務,其API應當具有很好的向后擴展性,當應內部需求 的改變或外部需求的改變的需要時,API將根據新的商業邏輯發生變化,此時不應當將API從根本上推翻重建,而應當具備增量式的可擴展的能力。
兼容性,其實兼容性與可擴展性是互通的,API的兼容性指的就是向后兼容性,高版本的API應該具備對低版本API的兼容性,也就是說使用高版本API的Web服務,應當能支持使用低版本API的調用。
高效性,API應該在堅持簡單性的前提下,兼顧高效性,當某些組合操作應用地非常頻繁的時候,我們應當為這樣的組合操作調用設計一個只需一次交互的單一入口調用,這樣能夠提升外部應用的效率,同時減輕Web服務的負載。
完備性,所謂完備性就是說整個API要覆蓋所有需要對外公開的功能,這相對而言是最好實現的目標,只要設計階段考慮得完備,就能達到完備性的要求。而且萬一發現不完備的情況,修正起來也是相對容易的。
Catalog Service
- save_category: 保存category,在這個API調用中,包含了更新和新建的操作,同時category的遷移也可以通過這個API來完成。
- delete_category: 刪除category,將指定category及其全部子元素從Catalog中刪除。
- find_category: 在catalog中定位尋找category,可以通過多種方式,比如名稱,比如關鍵字等。
- save_product: 保存product,在這個API調用中,同樣可以包含更新、新建和遷移的操作。
- delete_product: 刪除product,將指定product的信息從Catalog中刪除。
- find_product: 在catalog中定位尋找product,可以通過多種方式,比如名稱,比如所在的category,比如關鍵字等。
- get_categoryDetail: 獲取category的完整信息,包括包含的所有category的簡要信息和product的詳細信息。
- get_productDetail: 獲取product的完整信息。
- get_categoryInfo: 獲取category及其所有子孫category和product的所有信息。
在定義這些消息之前,我們首先需要確定的是category和product這兩個實體的XML描述格式。參照前文中的實體關系模型,我們可以將它們定義如下:
Category的具體描述格式:
clearcase/" target="_blank" >cccccc border=1>
<category categoryKey="..." parentCategoryKey="...">
<name>...</name>
<description>...</description>
</category>
|
Product的具體描述格式:
<product productKey="..." parentCategoryKey="...">
<name>...</name>
<description>...</description>
<compliantSpecBag />
<featureBag />
<parameterBag />
</category>
| 其中,compliantSpecBag、featureBag和parameterBag的具體格式分別如下:
<compliantSpecBag>
<specification specificationKey="..." /> *
</compliantSpecBag>
|
compliantSpecBag描述的是一種計算機產品遵循了哪些相關的業界標準。在這個聚集里面,specification這個元素可以出現多次,每一個條目分別表示其遵循了一種工業標準,比如一臺娛樂型的便攜式計算機可能就會遵循諸如USB1.0、IEEE1394等等的工業規范。
<featureBag>
<feature>...</feature> *
</featureBag>
|
featureBag描述的是一種計算機產品的重要特性。在這個聚集里面,feature這個元素可以出現多次,每一個條目使用字符串文本來描述某一種產品特性。比如一臺娛樂型的便攜式計算機可能的特性會包括"重量僅有2磅,厚度僅有1.9cm,超級便攜"這樣的特性描述。
<parameterBag>
<parameter> *
<keyName>...</keyName>
<keyValue>...</keyValue>
</parameter>
</parameterBag>
|
parameterBag描述的是一種計算機產品的相關技術參數。在這個聚集里面,parameter這個元素可以出現多次,每一個條目使用keyName和keyValue名值對來描述某一個技術參數。比如一臺便攜式計算機可能的技術參數會是TFT_Size10.1"。
在定義了核心的數據模型之后,我們就可以來分別定義具體的API消息了。
save_category
用于保存category的最新信息,使用這個API調用,可以完成對category的更新、新建和遷移的操作。
<save_category>
<authInfo>...</authInfo>
<category categoryKey="..." parentCategoryKey="..."> *
<name>...</name>
<description>...</description>
<category /> *
<product /> *
</category>
</save_category>
|
在上述的語法描述中,大家應該可以發現,save_category能夠用于保存一棵或多棵完整的category樹,而不光光是僅僅保存一個或多個category結點,這樣的設計是為了高效性的設計目標而做的調整。
當整個消息中的任意一個category或product所屬的標識自身實體的鍵值categoryKey或productKey為空,即表示這是一個新增的category或product,需要被插入到數據庫中,在返回消息中,將回送這些元素的鍵值。
當消息中任意一個category或product的parentCategoryKey沒有發生更改時,表明是要更新該元素的信息。而若parentCategoryKey發生更改的時候,表明該元素將從之前的由原有parentCategoryKey所標識的category結點下被遷移到由新的parentCategoryKey所標識的category結點下。當然如果包含了數據更新操作,同樣會實施該數據更新操作。
細心的讀者一定已經發現了在這個消息中,有一個authInfo元素,這是一個用于權限檢驗的授權令牌。在后面我將指明這個元素是如何獲取并使用的。
save_category消息調用的返回是一個或多個完整的被接受的category信息,與提交的信息的差別就是僅有概要信息,沒有相信信息,同時原先空著的鍵值都被填上Web服務所指派的鍵值。下面是一個返回消息的例子:
<result>
<category categoryKey="a01" parentCategoryKey="...">
<category categoryKey="a02" parentCategoryKey="a01" />
<category categoryKey="a03" parentCategoryKey="a01" />
<category categoryKey="a04" parentCategoryKey="a01" />
<product productKey="p01" parentCategoryKey="a01" />
<product productKey="p02" parentCategoryKey="a01" />
</category>
<category categoryKey="b01" parentCategoryKey="...">
<category categoryKey="b07" parentCategoryKey="b01" />
<category categoryKey="b08" parentCategoryKey="b01" />
<product productKey="p09" parentCategoryKey="b01" />
</category>
</result>
|
delete_category
用于刪除category的API調用,能夠將一個或多個category及其全部子元素從Catalog中刪除。
<delete_category>
<authInfo>...</authInfo>
<category categoryKey="..." /> *
</delete_category>
|
在上述的語法描述中,大家應該可以發現,save_category能夠用于刪除一個或多個使用categoryKey標識的category。當一個category被刪除時,其所有子元素(包括category子元素和product子元素)都將被刪除。
delete_category消息調用的返回是一個或多個被實施刪除的category信息的鍵值列表。
find_product
用于在某個catalog中搜尋滿足指定條件的product,在這個API消息中,支持多種查詢方式,比如名稱,比如按照所遵循的行業規范等。
<find_product>
<authInfo>...</authInfo>
<category categoryKey="..." />
<name />
<compliantSpecBag />
<parameterBag>
</find_product>
|
在find_product消息中,支持四種搜索條件:
- category,該元素描述了待搜索category子樹的根。表明待執行的搜索的空間是由該元素中的categoryKey所標識的category的所有子元素組成。
- name,這個name元素中描述的字符串是作為名串的最左子串存在的,在搜索中實施的也是最左匹配,比如在這個name元素中描述了"中國"那么"中國汽車","中國計算機"就會被匹配到,而"優質中國汽車"就不會被匹配到。
- compliantSpecBag,該元素中描述了一個業界規范的聚集,依靠這個搜索時指定的聚集,我們就可以將所有不符合這些規范的計算機產品排除在搜索結果集之外。例如該元素中包含了兩個規范USB1.1和IEEE1394,那么只有同時支持這兩個規范的產品才會被搜索到。
- parameterBag,該元素中描述了一個技術參數的聚集,其使用方式與compliantSpecBag類似,所有不符合所描述的技術參數指定的計算機產品將被排除在搜索結果集之外。
對于compliantSpecBag和parameterBag默認的搜索中的處理行為是邏輯與的方式,我們可以通過參數指定來定義邏輯或的方式。例如:
<compliantSpecBag>
<logicBehavior value="OR" />
<specification specificationKey="Key[USB1.1]" />
<specification specificationKey="Key[IEEE1394]" />
</compliantSpecBag>
|
這個例子表示需要搜索的計算機產品要么兼容USB1.1,要么兼容IEEE1394接口,那么不支持這兩種規范中任一規范的計算機產品將被排除在搜索結果集之外。
find_product消息調用的返回是一個或多個被匹配到的product信息,但改信息列表是一個概要信息的列表。下面是一個返回消息的例子:
<result>
<product productKey="p01" parentCategoryKey="a01" />
<name>...</name>
<description>...</description>
</product>
<product productKey="p02" parentCategoryKey="a01" />
<name>...</name>
<description>...</description>
</product>
</result>
|
在分析了上述三個API消息之后,我們不難理解save_product、delete_product和find_category和前面三個消息基本類似,且形式更為簡化,因此就不在詳細說明,浪費篇幅了。
而對于其余三個消息:get_categoryDetail,get_productDetail和get_categoryInfo,一來這三個消息相對簡單,傳入鍵值返回實體信息,二來經過前面的演示,相信大家應該有了一個具體的認識,因此在這里就不花篇幅定義具體消息了。
Member Service
對于Member Service而言,提供兩個API消息:
get_authToken
用于向Member Service請求一個認證令牌。在調用其他所有API 時都需要使用認證令牌。此函數在功能上等價于那些完成登錄請求的程序。
<get_authToken generic="2.0" xmlns="urn:uddi-org:api_v2"
userID="someLoginName"
password="somePassword" />
|
userID參數必須出現,表示在線服務所授權的個體用戶。Member Service提供對用戶所提供的用戶ID和密碼進行有效性檢查的方法。password參數必須出現,它表示了用戶ID所對應的密碼。
discard_authToken
用于通知Member Service,先前提供的認證令牌不再有效。當其他Web服務在Member Service接受到本消息之后,仍然收到這一認證令牌的使用,那么其他Web服務應當判斷其為非法。
<discard_authToken generic="2.0" xmlns="urn:uddi-org:api_v2" >
<authInfo/>
</discard_authToken>
|
authInfo這個參數是必需的,它是一個包含了認證令牌的元素。認證令牌可以使用 get_authToken API調用來獲得。
Feedback Service
- save_feedback: 保存feedback,在這個API調用中,包含了更新和新建的操作,同時category的遷移也可以通過這個API來完成。另外,使用這個API還能完成刪除的操作(之所以這樣設計是因為考慮到刪除是萬不得已才會發生的操作),刪除操作通過僅傳入feedbackKey和authInfo來完成操作。
- find_feedback: 在catalog中定位尋找feedback,比如名稱,比如categoryKey等。
- get_feedbackDetail: 獲取一個category下同層所有feedback的詳細信息。
- get_feedbackInfo: 獲取一個category下整個子樹中所有feedback的詳細信息。
Order Service
- request_order: 發出訂單請求,在這個API中包含了申請新訂單和取消訂單的兩個操作。當傳入的orderKey為空并包含其他細節內容時,即為申請新訂單操作。如果傳入的orderKey為已有的order的鍵值,同時不包含order的其他細節內容,那么即認為其是取消訂單的操作。該消息的返回分別可以指明對于訂單請求的接受或拒絕指示。
- get_orderDetail: 獲取訂單的詳細情況,用于在事后參閱。
- find_order: 搜索按照輸入參數指明的條件的相關訂單。
描述與注冊: 發布Web服務
在本文中,詳細描述和介紹了Web服務的API是如何設計和定義的,其中介紹了一些基本的設計和應用的模式。在本系列之后的文章中,我將以使用WSDL描述Web服務,以及使用UDDI注冊Web服務來結束這個系列。
參考資料
- Web Service 技術/評論網站
- 解決B2B電子商務應用交互和集成的InterOP Stack系列技術標準規范
- UDDI執行白皮書, UDDI-China.org, UDDI.org
- UDDI技術白皮書, UDDI-China.org, UDDI.org
- UDDI程序員API規范, UDDI-China.org, UDDI.org
- UDDI數據結構參考, UDDI-China.org, UDDI.org
- Web Service Description Language (WSDL) 1.0, IBM, 25 Sep 2000
- SOAP: Simple Object Access Protocol Specification 1.1, IBM, Microsoft, DevelopMentor, 2000
- Extensible Markup Language (XML) 1.0 (Second Edition), W3C, 6 Oct 2000
- 架構Web services系列
-
作者簡介 柴曉路: 上海得易電子商務技術有限公司(DealEasy)首席系統架構師、XML技術顧問。UDDI-China.org藍色火焰工作室(Blue Blaze Studio)成員。UDDI Advisor Group成員,WSUI Working Group成員。2000年獲復旦大學計算機科學碩士學位,曾在國際計算機科學學術會議(ICSC)、亞太區XML技術研討會(XML Asia/Pacific'99)、中國XML技術研討會(北京)、計算機科學期刊等各類國際、國內重要會議與期刊上發表論文多篇。專長于基于XML的系統集成和數據交換的技術研究,同時對數據庫、面向對象技術及CSCW等技術比較擅長。
|