摘 要: 介紹了基于XML的SOAP技術的特點和優(yōu)勢,描述了SOAP應用系統(tǒng)的架構,并揭示了其消息處理過程的機理和技術細節(jié),結合具體的SOAP處理器的實現(xiàn)模型設計和實現(xiàn)了SOAP處理器。
關鍵詞: 分布式應用 信息交換 RPC XML SOAP協(xié)議 WSDL SOAP處理器
XML和簡單對象訪問協(xié)議(Simple Object Access Protocol,SOAP)帶來了信息交換技術革命性的進步,極大地促進了分布式應用的發(fā)展。目前,在基于SOAP信息交換應用的集成化開發(fā)環(huán)境和工具中關于SOAP的技術對開發(fā)人員基本上是透明的,即屏蔽和隱藏了SOAP實現(xiàn)和處理的細節(jié)。這樣做可以方便開發(fā)工作,但卻不利于開發(fā)者真正透徹地掌握SOAP的關鍵技術。深入了解SOAP消息的處理過程和SOAP處理器的工作機理,可以對分布式應用進行更加靈活地控制,甚至可以自行開發(fā)SOAP消息處理器以適應各種特殊的處理需求。
1 SOAP概述
SOAP是一種應用程序之間進行數(shù)據(jù)通信的機制??蓴U展標記語言XML作為數(shù)據(jù)表達通用的中性語言,使分布式應用的各計算節(jié)點在數(shù)據(jù)的“表示層”得到了統(tǒng)一,也使得基于XML的SOAP成為用于數(shù)據(jù)交換的、方便的封裝協(xié)議。廣義上的SOAP是網(wǎng)絡表示層的協(xié)議,是標準的信息交換工具,可以用來實現(xiàn)消息系統(tǒng),但其目前最主要的應用是進行遠程過程調(diào)用(RPC)。應用SOAP技術,可以構建基于消息通信的、松散耦合的、跨平臺的分布式處理系統(tǒng),這極大地適應了互聯(lián)網(wǎng)環(huán)境的應用需求。
2 SOAP消息處理模型
2.1 SOAP的應用架構和消息處理模型框架
SOAP成功地解決了異構網(wǎng)絡環(huán)境中的軟件組件和應用程序之間進行可靠信息交換的難題。以Web Service為例,其SOAP RPC的應用架構如圖1所示。一般開發(fā)環(huán)境都隱藏了SOAP消息處理的過程,這部分功能封裝于由開發(fā)環(huán)境自動生成的客戶端和服務器端的SOAP代理模塊中,其中都使用了編譯好的高層類庫,用戶據(jù)此難以探究其內(nèi)部的處理細節(jié)。
實際上,客戶端和服務器端的SOAP代理模塊內(nèi)部做了大量的處理工作。SOAP RPC的處理過程如圖2所示。客戶端模塊按照Web Service使用接口(一般用WSDL文檔進行描述)要求的格式和規(guī)范,通過XML處理器將客戶端的RPC調(diào)用編碼成SOAP請求消息(SOAP消息的串行化)。SOAP請求消息中按規(guī)定封裝了請求服務所必需的信息,借助傳輸協(xié)議(如HTTP)傳送到服務器端;服務器的傳輸協(xié)議監(jiān)聽器得到傳輸?shù)膬?nèi)容,由服務器端的代理模塊按照WSDL文檔描述的Web Service接口的信息采用XML處理器對SOAP請求消息進行解析,提取出適當?shù)男畔?生成提供相應的Web服務的對象,調(diào)用請求的方法,得到服務程序的處理結果,再按WSDL文檔的要求將服務處理結果生成(串行化)SOAP響應消息,借助傳輸協(xié)議傳回客戶端;客戶端的代理按照WSDL文檔描述的信息解析(反串行化)SOAP響應消息,提取出適當?shù)男畔⒎祷乜蛻舫绦?。在客戶端和服務器端對SOAP消息進行串行化和反串行化期間,涉及到客戶程序的數(shù)據(jù)類型與XML的類型系統(tǒng)XSD(或SOAP規(guī)范的類型系統(tǒng))之間,以及XML的類型系統(tǒng)XSD與服務程序的數(shù)據(jù)類型之間的相互映射,還有對象參數(shù)的序列化和反序列化工作。
當SOAP與HTTP綁定時,服務器端的消息監(jiān)聽可以采用ASP或ISAPI處理方式。
SOAP消息的生成和解析工作與WSDL文檔密切相關,只有遵照Web Service對應的WSDL文檔中描述的信息格式,SOAP消息才能得到正確的、自動化的處理。
2.2 WSDL簡介
WSDL(Web Service Description Language)是一種接口定義語言(IDL)。它以一種XML模式來描述Web Service的接口。服務的使用方根據(jù)這些描述信息來理解如何使用服務。由于描述方法和格式具有統(tǒng)一的標準和規(guī)范,因此便于由機器來自動處理描述信息。實際上,很多開發(fā)環(huán)境就是由軟件工具根據(jù)服務模塊自動生成相應的WSDL文檔。WSDL文檔使用這些元素來定義Web Service的使用接口:Types、Message、Operation、Port Type、Binding、Port、Service。
在具體實現(xiàn)SOAP處理器的過程中需要編程訪問WSDL文檔。為使篇幅簡潔,本文將采用MS SOAP TK 3.0中提供的WSDL文檔模型對象接口(詳情可參見MSTK3.0開發(fā)文檔)來編程分析WSDL文檔,即通過編程對象及其方法遍歷文檔中的元素,得到的接口描述信息用以處理SOAP消息。
3 實現(xiàn)SOAP處理器的功能
由圖2所示的SOAP消息處理器的功能和過程架構,可以實現(xiàn)自行開發(fā)的SOAP處理器。
3.1 具體的實現(xiàn)模型
由于SOAP消息和WSDL文檔都是基于XML格式的,所以代理(處理器)的工作主要是分析和處理XML文檔。可以根據(jù)SOAP消息封裝格式、編碼規(guī)則、RPC表示以及WSDL文檔結構的協(xié)議規(guī)范,采用任一種XML解析器工具來處理SOAP和WSDL這類特殊的XML文檔(如圖2所示)。本文將采用MSTK3.0中的低層API(封裝了XML處理功能)來實現(xiàn)SOAP代理,處理過程反映了技術機理和細節(jié)。將準備實現(xiàn)的客戶端和服務器端的SOAP代理類命名為mySoapClient和mySoapServer。其內(nèi)部實現(xiàn)過程模型分別如圖3和圖4所示。
3.2 具體實現(xiàn)
下面采用VB6.0來實現(xiàn)mySoapClient類和mySoapServer類。
3.2.1 客戶端SOAP代理
新建ActiveX DLL工程MyClientSoap,添加并引用Microsoft Soap Type Library v3.0。將以下代碼加入mySoapClient類模塊中。
Dim Port As IWSDLPort
Public Sub Initialize(ByVal WSDLFileName As String,
Optional ByVal ServiceName As String=″″,
Optional ByVal PortName As String=″″,
Optional ByVal WSMLFileName As String=″″)
Dim Fetched As Long
Dim WSDLReader As New WSDLReader30
′load WSDL file
WSDLReader.Load WSDLFileName,WSMLFileName
′get the service
Dim ServiceEnumerator As IEnumWSDLService,Service As IWSDLService
WSDLReader.GetSoapServices ServiceEnumerator
If ServiceName=″″Then
ServiceEnumerator.Next 1,Service,Fetched
Else
ServiceEnumerator.Find ServiceName,Service
End If
′get the port
Dim PortEnumerator As IEnumWSDLPorts
Service.GetSoapPorts PortEnumerator
If PortName=″″Then
PortEnumerator.Next 1,Port,Fetched
Else
PortEnumerator.Find PortName,Port
End If
End Sub
Public Function Invoke(ByVal OperationName As String,
ParamArray Parameter() As Variant) As Variant
′find the operation
Dim OperationEnumerator As IEnumWSDLOperations,
Operation As IWSDLOperation
Port.GetSoapOperations OperationEnumerator
OperationEnumerator.Find OperationName,Operation
′prepare request
Dim MapperEnumerator As IEnumSoapMappers,
Mapper As ISoapMapper
Operation.GetOperationParts MapperEnumerator
Dim Fetched As Long
MapperEnumerator.Next 1,Mapper,Fetched
Do While Fetched=1
If (Mapper.IsInput=smInput) Or (Mapper.IsInput=smInOut) Then
Mapper.ComValue=Parameter(Mapper.ParameterOrder)
End If
MapperEnumerator.Next 1,Mapper,Fetched
Loop
′construct the request message and send it.
′(that is,invoking the operation and getting result)
Dim Serializer As SoapSerializer30
Dim Connector As SoapConnector30
Set Connector=New HttpConnector30
Connector.ConnectWSDL Port
Connector.BeginMessageWSDL Operation
Set Serializer=New SoapSerializer30
Serializer.Init Connector.InputStream
Serializer.StartEnvelope
Serializer.StartBody
Operation.Save Serializer,True′writes the XML
Serializer.EndBody
Serializer.EndEnvelope
′load response
Dim SoapReader As New SoapReader30
SoapReader.Load Connector.OutputStream
Operation.Load SoapReader,False
′return the outgoing parameters and result
MapperEnumerator.Reset
MapperEnumerator.Next 1,Mapper,Fetched
Do While Fetched=1
If Mapper.IsInput=smOutput Then
If Mapper.VariantType=vbObject Then
Set Invoke=Mapper.ComValue
Else
Invoke=Mapper.ComValue
End If
ElseIf Mapper.IsInput=smInOut Then
Parameter(Mapper.ParameterOrder)=Mapper.ComValue
End If
MapperEnumerator.Next 1,Mapper,Fetched
Loop
End Function
將以上代理編譯即可生成MyClientSoap.dll。將mySoapClient類實例化就成為客戶端SOAP代理對象。mySoapClient類向外提供了二個可調(diào)用的接口:(1)Initialize方法利用WSDL文檔中描述的Web Service接口消息來初始化客戶端代理對象,用戶還可指定要遠程調(diào)用的Web Service的服務名稱ServiceName和端口名稱PortName。(2)Invoke方法向客戶程序提供了使用Web Service的接口,用戶只需提供Web Service中的方法名稱和此方法的參數(shù),就可以調(diào)用Web Service。
3.2.2 服務器端SOAP代理
新建ActiveX DLL工程MyServerSoap,并添加引用Microsoft Soap Type Library v3.0。
將以下代碼加入mySoapServer類模塊中。
Dim WSDLReader As WSDLReader30
Public Sub Initialize(ByVal WSDLFileName As String,ByVal WSMLFileName As String)
Set WSDLReader=New WSDLReader30
WSDLReader.SetProperty ″LoadOnServer″,True
WSDLReader.Load WSDLFileName,WSMLFileName
End Sub
Public Sub ProcessRequest(ByVal Request As IStream,ByVal Response As IStream)
Dim WSDLPort As IWSDLPort
Dim WSDLOperation As IWSDLOperation
Dim Serializer As New SoapSerializer30
Dim SoapReader As New SoapReader30
SoapReader.Load Request
WSDLReader.ParseRequest SoapReader,WSDLPort,
WSDLOperation
WSDLOperation.Load SoapReader,True
Serializer.Init Response
Serializer.StartEnvelope
WSDLOperation.ExecuteOperation SoapReader,Serializer
Serializer.StartBody
WSDLOperation.Save Serializer,False
Serializer.EndBody
Serializer.EndEnvelope
End Sub
編譯后生成MyServerSoap.dll。將mySoapServer類實例化就成為服務器端SOAP代理對象。Initialize方法利用WSDL文檔來初始化服務器端代理對象。ProcessRequest方法分析接收到的SOAP請求消息,調(diào)用相應的Web Service方法,將結果編碼成SOAP響應消息回傳。
以上詳細剖析了SOAP消息的處理過程,設計實現(xiàn)了SOAP處理器。實際上,本文中實現(xiàn)代理類的代碼還可進一步細化,甚至完全可以不引用MSTK3.0中的低層API類庫,而采用XML解析器來編寫SOAP處理器。由于篇幅所限,還有一些細節(jié)問題未能進一步展開探討,如復雜數(shù)據(jù)類型的編碼、SOAP頭部的處理、錯誤的捕獲和附件的處理等。本文已實現(xiàn)了SOAP處理器最重要的核心功能框架(消息的構建、傳輸和解析等),用戶可以在此基礎上,增加調(diào)用附加功能的接口,這樣可以實現(xiàn)功能更加豐富的SOAP處理器。