[pre]WebServices入門
——理論篇
瑞聯(lián)科技(中國)有限公司 李春林[/pre]
本文檔是用ctrl+c -> ctrl+v產(chǎn)生出來的入門級(jí)文檔,主要是想說明什么是webservices,webservices的架構(gòu),以及幾個(gè)相關(guān)的xml文檔。由于小弟知識(shí)及技術(shù)非常有限,文中不妥之處請(qǐng)各位兄臺(tái)指正,小弟在此謝過啦。
什么是webservices?
從表面上看:Webservices 就是一個(gè)應(yīng)用程序,它向外界暴露出一個(gè)能夠通過Web進(jìn)行調(diào)用的API。這就是說,你能夠用編程的方法通過Web來調(diào)用這個(gè)應(yīng)用程序。我們把調(diào)用這個(gè)Webservices 的應(yīng)用程序叫做客戶。
更專業(yè)的描述如下:Webservices是描述一些操作(利用標(biāo)準(zhǔn)化的 XML 消息傳遞機(jī)制可以通過網(wǎng)絡(luò)訪問這些操作)的接口。Webservices是用標(biāo)準(zhǔn)的、規(guī)范的 XML 概念描述的,稱為 Webservices的服務(wù)描述。這一描述囊括了與服務(wù)交互需要的全部細(xì)節(jié),包括消息格式(詳細(xì)描述操作)、傳輸協(xié)議和位置。該接口隱藏了實(shí)現(xiàn)服務(wù)的細(xì)節(jié),允許獨(dú)立于實(shí)現(xiàn)服務(wù)基于的硬件或軟件平臺(tái)和編寫服務(wù)所用的編程語言使用服務(wù)。這允許并支持基于 Webservices的應(yīng)用程序成為松散耦合、面向組件和跨技術(shù)實(shí)現(xiàn)。Webservices履行一項(xiàng)特定的任務(wù)或一組任務(wù)。Webservices可以單獨(dú)或同其它 Webservices一起用于實(shí)現(xiàn)復(fù)雜的聚集或商業(yè)交易,以及企業(yè)集成(EAI)。
Webservices模型
Webservices體系結(jié)構(gòu)基于三種角色(服務(wù)提供者、服務(wù)注冊(cè)中心和服務(wù)請(qǐng)求者)之間的交互。交互涉及發(fā)布、查找和綁定操作。這些角色和操作一起作用于 Webservices構(gòu)件:
Webservices軟件模塊及其描述。在典型(并非 非典^_^)情況下,服務(wù)提供者托管可通過網(wǎng)絡(luò)訪問的軟件模塊(Webservices的一個(gè)實(shí)現(xiàn))。服務(wù)提供者定義 Web 服務(wù)的服務(wù)描述并把它發(fā)布到服務(wù)請(qǐng)求者或服務(wù)注冊(cè)中心。服務(wù)請(qǐng)求者使用查找操作來從本地或服務(wù)注冊(cè)中心檢索服務(wù)描述,然后使用服務(wù)描述與服務(wù)提供者進(jìn)行綁定并調(diào)用 Web 服務(wù)實(shí)現(xiàn)或同它交互。服務(wù)提供者和服務(wù)請(qǐng)求者角色是邏輯結(jié)構(gòu),因而服務(wù)可以表現(xiàn)兩種特性。下圖 圖示了這些操作、提供這些操作的組件及它們之間的交互。
Webservices協(xié)議棧
要以一種可互操作的方式執(zhí)行發(fā)布、發(fā)現(xiàn)和綁定這三個(gè)操作,必須有一個(gè)包含每一層標(biāo)準(zhǔn)的 Webservices協(xié)議棧。下圖展示了一個(gè)概念性 Webservices協(xié)議棧。上面的幾層建立在下面幾層提供的功能之上。垂直的條表示在協(xié)議棧中每一層必須滿足的需求。左面的文本表示協(xié)議棧的那一層所應(yīng)用的標(biāo)準(zhǔn)技術(shù)。
下面對(duì)上面是概念性的協(xié)議棧中,的每一層做一個(gè)粗糙的說明:
第一層(Network):這一層的這些協(xié)議都是現(xiàn)在運(yùn)用比較廣泛的協(xié)議啦,現(xiàn)在HTTP運(yùn)用的最多啦,好處是顯而易見的,其他的我就不多說了吧。(主要我怕我說出來會(huì)錯(cuò)誤百出,被大家嘲笑。 *_*)。
第二層(XML-Based Messaging)這一層中主要體現(xiàn)怎么去調(diào)用Webservices。現(xiàn)在運(yùn)用比較廣泛的主要有兩種,一種是xml-rpc(XML-Remote Procedure Call), 另一種是SOAP(Simple Object Access Protocal)。相比之下SOAP比XML-RPC有一定的優(yōu)勢:SOAP在處理復(fù)雜數(shù)據(jù)(如數(shù)組等)要比XML-RPC更容易一些;XML-RPC沒有標(biāo)準(zhǔn)化錯(cuò)誤代碼;下面我們著重看看SOAP:
什么是SOAP?
對(duì)SOAP的一種簡單理解:
SOAP是一種XML Application,SOAP簡單的理解,就是這樣的一個(gè)開放協(xié)議SOAP=RPC+HTTP+XML:采用HTTP作為底層通訊協(xié)議;RPC作為一致性的調(diào)用途徑,XML作為數(shù)據(jù)傳送的格式,允許服務(wù)提供者和服務(wù)客戶經(jīng)過防火墻在INTERNET進(jìn)行通訊交互。如下圖:
對(duì)SOAP更深一步的理解:
SOAP簡單對(duì)象訪問協(xié)議是在分散或分布式的環(huán)境中交換信息的簡單的協(xié)議,是一個(gè)基于XML的協(xié)議,它包括四個(gè)部分:SOAP封裝(envelop),封裝定義了一個(gè)描述消息中的內(nèi)容是什么,是誰發(fā)送的,誰應(yīng)當(dāng)接受并處理它以及如何處理它們的框架,如下圖;SOAP編碼規(guī)則(encoding rules),用于表示應(yīng)用程序需要使用的數(shù)據(jù)類型的實(shí)例,一般遵循XMLSchema(定義了一系列的簡單數(shù)據(jù)類型)規(guī)范; SOAP RPC表示(RPC representation),表示遠(yuǎn)程過程調(diào)用和應(yīng)答的協(xié)定;SOAP綁定(binding),使用底層協(xié)議交換信息。雖然這四個(gè)部分都作為SOAP的一部分,作為一個(gè)整體定義的,但他們?cè)诠δ苌鲜窍嘟坏摹⒈舜霜?dú)立的。特別的,信封和編碼規(guī)則是被定義在不同的XML命名空間(namespace)中,這樣使得定義更加簡單。
圖:SOAP封裝(envelop)
下面讓我們來看一個(gè)SOAP的例子:
[pre]POST /calendar-request HTTP/1.1
Host: www.todaytech.com.cn
Content-Type: text/plain; charset="utf-8"
Content-Length: 507
SOAPAction:””
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:searchPaynoteResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://external.charge.gfmis.todaytech.com">
<searchPaynoteReturn href="#id0"/>
</ns1:searchPaynoteResponse>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:ExternalPaynoteVO"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://vo.charge.gfmis.todaytech.com">
<paynoteNO xsi:type="xsd:string">0300000003004</paynoteNO>
<startDate xsi:type="xsd:string" xsi:nil="true"/>
<disaID xsi:type="xsd:string" xsi:nil="true"/>
<annotation xsi:type="xsd:string" xsi:nil="true"/>
<chargeItemNO3 xsi:type="xsd:string" xsi:nil="true"/>
<amount xsi:type="xsd:double">0.0</amount>
<chargeItemNO2 xsi:type="xsd:string" xsi:nil="true"/>
<loginKey xsi:type="xsd:string">YCpTEwKEw</loginKey>
<chargeItemNO1 xsi:type="xsd:string" xsi:nil="true"/>
<userSign xsi:type="xsd:string" xsi:nil="true"/>
<operator xsi:type="xsd:string" xsi:nil="true"/>
<userCert xsi:type="xsd:string" xsi:nil="true"/>
<quantity3 xsi:type="xsd:double">0.0</quantity3>
<quantity2 xsi:type="xsd:double">0.0</quantity2>
<unitName xsi:type="xsd:string" xsi:nil="true"/>
<srvSign xsi:type="xsd:string" xsi:nil="true"/>
<quantity1 xsi:type="xsd:double">0.0</quantity1>
<srvCert xsi:type="xsd:string" xsi:nil="true"/>
<externalPaynoteNO xsi:type="xsd:string" xsi:nil="true"/>
<status xsi:type="xsd:int">1</status>
<randStr xsi:type="xsd:string" xsi:nil="true"/>
<returnCode xsi:type="xsd:int">0</returnCode>
<endDate xsi:type="xsd:string" xsi:nil="true"/>
<price3 xsi:type="xsd:double">0.0</price3>
<price2 xsi:type="xsd:double">0.0</price2>
<price1 xsi:type="xsd:double">0.0</price1>
<unitNO xsi:type="xsd:string" xsi:nil="true"/>
<payerName xsi:type="xsd:string" xsi:nil="true"/>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>[/pre]
第三層(Service Description):在這一層中主要是我們服務(wù)的描述,向客戶端說明我們的服務(wù),告訴客戶端、我們的提供了什么樣的接口可供調(diào)用(WHAT),怎么樣去調(diào)用(HOW),到那去調(diào)用(WHERE)。在這一層中主要的協(xié)議是WSDL(Web Services Description Language)。WSDL 是一種XML Application,它的作用就是給客戶端描述我們接口的WHAT,HOW,WHERE,也就是說:WSDL 服務(wù)定義為分布式系統(tǒng)提供了可機(jī)器識(shí)別的SDK文檔,并且可用于描述自動(dòng)執(zhí)行應(yīng)用程序通信中所涉及的細(xì)節(jié)。
WSDL 文檔將Web服務(wù)定義為服務(wù)訪問點(diǎn)或端口的集合。在 WSDL 中,由于服務(wù)訪問點(diǎn)和消息的抽象定義已從具體的服務(wù)部署或數(shù)據(jù)格式綁定中分離出來,因此可以對(duì)抽象定義進(jìn)行再次使用:消息,指對(duì)交換數(shù)據(jù)的抽象描述;而端口類型,指操作的抽象集合。用于特定端口類型的具體協(xié)議和數(shù)據(jù)格式規(guī)范構(gòu)成了可以再次使用的綁定。將Web訪問地址與可再次使用的綁定相關(guān)聯(lián),可以定義一個(gè)端口,而端口的集合則定義為服務(wù)。因此,WSDL 文檔在Web服務(wù)的定義中使用下列元素:
• Types - 數(shù)據(jù)類型定義的容器,它使用某種類型系統(tǒng)(一般地使用XML Schema中的類型系統(tǒng))。
• Message - 通信消息的數(shù)據(jù)結(jié)構(gòu)的抽象類型化定義。使用Types所定義的類型來定義整個(gè)消息的數(shù)據(jù)結(jié)構(gòu)。
• Operation - 對(duì)服務(wù)中所支持的操作的抽象描述,一般單個(gè)Operation描述了一個(gè)訪問入口的請(qǐng)求/響應(yīng)消息對(duì)。
• PortType - 對(duì)于某個(gè)訪問入口點(diǎn)類型所支持的操作的抽象集合,這些操作可以由一個(gè)或多個(gè)服務(wù)訪問點(diǎn)來支持。
• Binding - 特定端口類型的具體協(xié)議和數(shù)據(jù)格式規(guī)范的綁定。
• Port - 定義為協(xié)議/數(shù)據(jù)格式綁定與具體Web訪問地址組合的單個(gè)服務(wù)訪問點(diǎn)。
• Service - 相關(guān)服務(wù)訪問點(diǎn)的集合。
我們可以參考下圖,來理解一下WSDL文檔的結(jié)構(gòu)組織:
說明:其中,
Types是一個(gè)數(shù)據(jù)類型定義的容器,包含了所有在消息定義中需要的XML元素的類型定義,它一般遵循XMLSchema的規(guī)范。
Message具體定義了在通信中使用的消息的數(shù)據(jù)結(jié)構(gòu),Message元素包含了一組Part元素,每個(gè)Part元素都是最終消息的一個(gè)組成部分,每個(gè)Part都會(huì)引用一個(gè)DataType來表示它的結(jié)構(gòu)。Part元素不支持嵌套(可以使用DataType來完成這方面的需要),都是并列出現(xiàn)。
PortType具體定義了一種服務(wù)訪問入口的類型,何謂訪問入口的類型呢?就是傳入/傳出消息的模式及其格式。一個(gè)PortType可以包含若干個(gè)Operation,而一個(gè)Operation則是指訪問入口支持的一種類型的調(diào)用。在WSDL里面支持四種訪問入口調(diào)用的模式:
1. 單請(qǐng)求;
2. 單響應(yīng);
3. 請(qǐng)求/響應(yīng);
4. 響應(yīng)/請(qǐng)求。
Service描述的是一個(gè)具體的被部署的Web服務(wù)所提供的所有訪問入口的部署細(xì)節(jié),一個(gè)Service往往會(huì)包含多個(gè)服務(wù)訪問入口,而每個(gè)訪問入口都會(huì)使用一個(gè)Port元素來描述。
Port描述的是一個(gè)服務(wù)訪問入口的部署細(xì)節(jié),包括通過哪個(gè)Web地址(URL)來訪問,應(yīng)當(dāng)使用怎樣的消息調(diào)用模式來訪問等。其中消息調(diào)用模式則是使用Binding結(jié)構(gòu)來表示。
Binding結(jié)構(gòu)定義了某個(gè)PortType與某一種具體的網(wǎng)絡(luò)傳輸協(xié)議或消息傳輸協(xié)議相綁定,從這一層次開始,描述的內(nèi)容就與具體服務(wù)的部署相關(guān)了。比如可以將PortType與SOAP/HTTP綁定,也可以將PortType與MIME/SMTP相綁定等。
下面我們給出一個(gè)WSDL的文檔實(shí)例:
[pre]<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://external.charge.gfmis.todaytech.com"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://external.charge.gfmis.todaytech.com-impl"
xmlns:intf="http://external.charge.gfmis.todaytech.com"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns2="http://vo.charge.gfmis.todaytech.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema targetNamespace="http://vo.charge.gfmis.todaytech.com"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="ExternalPaynoteVO">
<sequence>
<element name="amount" type="xsd:double"/>
<element name="annotation" nillable="true" type="xsd:string"/>
<element name="chargeItemNO1" nillable="true" type="xsd:string"/>
<element name="chargeItemNO2" nillable="true" type="xsd:string"/>
<element name="chargeItemNO3" nillable="true" type="xsd:string"/>
<element name="disaID" nillable="true" type="xsd:string"/>
<element name="endDate" nillable="true" type="xsd:string"/>
<element name="externalPaynoteNO" nillable="true" type="xsd:string"/>
<element name="loginKey" nillable="true" type="xsd:string"/>
<element name="operator" nillable="true" type="xsd:string"/>
<element name="payerName" nillable="true" type="xsd:string"/>
<element name="paynoteNO" nillable="true" type="xsd:string"/>
<element name="price1" type="xsd:double"/>
<element name="price2" type="xsd:double"/>
<element name="price3" type="xsd:double"/>
<element name="quantity1" type="xsd:double"/>
<element name="quantity2" type="xsd:double"/>
<element name="quantity3" type="xsd:double"/>
<element name="randStr" nillable="true" type="xsd:string"/>
<element name="returnCode" type="xsd:int"/>
<element name="srvCert" nillable="true" type="xsd:string"/>
<element name="srvSign" nillable="true" type="xsd:string"/>
<element name="startDate" nillable="true" type="xsd:string"/>
<element name="status" type="xsd:int"/>
<element name="unitNO" nillable="true" type="xsd:string"/>
<element name="unitName" nillable="true" type="xsd:string"/>
<element name="userCert" nillable="true" type="xsd:string"/>
<element name="userSign" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<element name="ExternalPaynoteVO" nillable="true" type="tns2:ExternalPaynoteVO"/>
</schema>
</wsdl:types>
<wsdl:message name="logoutRequest">
<wsdl:part name="epnvo" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="searchPaynoteResponse">
<wsdl:part name="searchPaynoteReturn" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="searchPaynoteRequest">
<wsdl:part name="epnvo" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="genPaynoteResponse">
<wsdl:part name="genPaynoteReturn" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="loginResponse">
<wsdl:part name="loginReturn" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="logoutResponse">
<wsdl:part name="logoutReturn" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="genPaynoteRequest">
<wsdl:part name="epvo" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:message name="loginRequest">
<wsdl:part name="epnvo" type="tns2:ExternalPaynoteVO"/>
</wsdl:message>
<wsdl:portType name="ExternalInterface">
<wsdl:operation name="login" parameterOrder="epnvo">
<wsdl:input message="intf:loginRequest" name="loginRequest"/>
<wsdl:output message="intf:loginResponse" name="loginResponse"/>
</wsdl:operation>
<wsdl:operation name="logout" parameterOrder="epnvo">
<wsdl:input message="intf:logoutRequest" name="logoutRequest"/>
<wsdl:output message="intf:logoutResponse" name="logoutResponse"/>
</wsdl:operation>
<wsdl:operation name="genPaynote" parameterOrder="epvo">
<wsdl:input message="intf:genPaynoteRequest"
name="genPaynoteRequest"/>
<wsdl:output message="intf:genPaynoteResponse"
name="genPaynoteResponse"/>
</wsdl:operation>
<wsdl:operation name="searchPaynote" parameterOrder="epnvo">
<wsdl:input message="intf:searchPaynoteRequest"
name="searchPaynoteRequest"/>
<wsdl:output message="intf:searchPaynoteResponse"
name="searchPaynoteResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ExternalInterfaceSoapBinding"
type="intf:ExternalInterface">
<wsdlsoap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="login">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="loginRequest">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:input>
<wsdl:output name="loginResponse">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="logout">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="logoutRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:input>
<wsdl:output name="logoutResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="genPaynote">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="genPaynoteRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:input>
<wsdl:output name="genPaynoteResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="searchPaynote">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="searchPaynoteRequest">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:input>
<wsdl:output name="searchPaynoteResponse">
<wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://external.charge.gfmis.todaytech.com" use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ExternalInterfaceService">
<wsdl:port binding="intf:ExternalInterfaceSoapBinding" name="ExternalInterface">
<wsdlsoap:address location="http://localhost:7001/gfmis/services/ExternalInterface"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>[/pre]
第四層(Service Publication):
第五層(Service Discovery):這兩層都是關(guān)于UDDI的協(xié)議,我們暫時(shí)用不上,現(xiàn)在也暫時(shí)沒有,以后補(bǔ)上(^_^)。
posted on 2007-03-23 10:29
圣域飛俠 閱讀(182)
評(píng)論(0) 編輯 收藏 所屬分類:
轉(zhuǎn)載