一个简单的SOAP服务应用

发表于:2007-07-01来源:作者:点击数: 标签:
下面是一个简单例子: 我们建立一个服务端来计算销售交易的税款。按照传统的VB术语,即建立一个函数,定义如下: Public Function GetSalesTax(ByVal pSalesTotal As Double) as Double GetSalesTax = pSalesTotal * 0.04 End Function 一个粗糙的函数,但可


下面是一个简单例子:
我们建立一个服务端来计算销售交易的税款。按照传统的VB术语,即建立一个函数,定义如下:
  Public Function GetSalesTax(ByVal pSalesTotal As Double) as Double
   GetSalesTax = pSalesTotal * 0.04
  End Function

一个粗糙的函数,但可作为示例(本例只能用于税率为4%的地方)。
这个函数定义了一个函数名(GetSalesTax),一个参数(pSalesTotal – 销售金额)和一个返回值(函数返回值)。按照面向对象原则,可以认为pSalesTotal是一个"IN"参数,GetSalesTax返回值是一个"OUT"参数。因此我们的SOAP服务端就要侦听客户发出的调用GetSalesTax的请求和传递的"IN"参数(销售金额),然后返回带有"OUT"参数的回应,向客户返回所需税款。

客户端
下面是用VB建立一个呼叫服务的客户端程序:
  dblSalesTax = GetSalesTax(100)
  得到返回值$4。
  
  如果GetSalesTax函数是一个外部对象,比如在MTS服务器上,就要调用服务器上的DLL模块:
  Dim objTax As New CTaxCalc
  dblSalesTax = objTax.GetSalesTax(100)

在SOAP系统中,远程调用的方式略有不同,呼叫是通过XML文件传送到服务器的。XML文件里有调用的函数名和相应的参数:
  <GetSalesTax>
   <SalesTotal>100</SalesTotal>
  <GetSalesTax>

为确保服务器能够识别和解释客户请求,呼叫指令被包装到一个称之为SOAP信封的大文件里。这个信封使用的是SOAP封装标准的通用命名空间:
  <SOAP:Envelope xmlns:SOAP="urn:schemas-xmlsoap-org:soap.v1">
   <SOAP:Header></SOAP:Header>
   <SOAP:Body>
    <GetSalesTax>
     <SalesTotal>100</SalesTotal>
    <GetSalesTax>
   </SOAP:Body>
  </SOAP:Envelope>

最后,加入函数调用的命名空间,起到函数声明的作用:
  <SOAP:Envelope xmlns:SOAP="urn:schemas-xmlsoap-org:soap.v1">
   <SOAP:Header></SOAP:Header>
   <SOAP:Body>
    <m:GetSalesTax xmlns:m="urn:myserver/soap:TaxCalc">
     <SalesTotal>100</SalesTotal>
    </m:GetSalesTax>
   </SOAP:Body>
  </SOAP:Envelope>

现在,已经准备好客户请求文件,可以送往服务端了。发送请求很简单,可以跟浏览器表单一样,用HTTP post方式。浏览器可以向服务端发送复杂的表单,.NET可以向服务器发送VB代码,但我使用XMLHTTP(IE 5以上版本才能用)。

假设strEnvelope含有XML文件格式的请求,发送格式如下:
  Dim objHTTP As New MSXML.XMLHTTPRequest
  Dim strEnvelope As String

  @#设定发往本地服务器
  objHTTP.open "post", "http://localhost/soap/soap.asp"

  @#设定标准SOAP/ XML文件头格式
  objHTTP.setRequestHeader "Content-Type", "text/xml"

  @#设置呼叫函数请求
  objHTTP.setRequestHeader "SOAPMethodName", _
   "urn:myserver/soap:TaxCalc#GetSalesTax"

  @#呼叫SOAP
  objHTTP.send strEnvelope

  @#取得返回值
  strReturn = objHTTP.responseBody

至此,客户端完成了向服务端发送请求的过程。现在回到服务端,看看服务端如何侦听客户请求并作出响应。

服务端
服务端要能够接收客户发出的HTTP请求,在本地服务器(http://localhost/soap.asp)接收到客户请求时作出回应。因此服务端要能够解析客户端发出的XML格式(SOAP封装)的请求,取出调用的函数名和参数。

服务端文件是soap.asp,它接收客户请求的做法是:
  Set objReq = Server.CreateObject("Microsoft.XMLDOM")
  objReq.Load Request

然后用XSL样式从封装的XML文件中取出参数:
  strQuery = "SOAP:Envelope/SOAP:Body/m:GetSalesTax/SalesTotal"
  varSalesTotal = objReq.SelectSingleNode(strQuery).Text

根据参数计算税款:
  varSalesTax = varSalesTotal * 0.04

在将结果返回给客户之前,要按SOAP标准做格式化封装。过程与客户端类似,只是把"IN"参数改换为"OUT"参数,并将函数标记名标为回应:
  <SOAP:Envelope xmlns:SOAP="urn:schemas-xmlsoap-org:soap.v1">
   <SOAP:Header></SOAP:Header>
   <SOAP:Body>
   <m:GetSalesTaxResponse xmlns:m="urn:myserver/soap:TaxCalc">
    <SalesTax>4</SalesTax>
   </m:GetSalesTaxResponse>
   </SOAP:Body>
  </SOAP:Envelope>

可以用字符串方式构造这个回应文件,也可以创建一个DOM对象,增加一个节点。
文件返回给客户后,客户经过解码就能得到结果:
  Dim objReturn As New MSXML.DomDocument
  objReturn.LoadXML strReturn
  strQuery = _
  "SOAP:Envelope/SOAP:Body/m:GetSalesTaxResponse/SalesTax"
  dblTax = objReturn.SelectSingleNode(strQuery).Text

这样就完成了一个简单的SOAP服务应用。虽然Visual Studio 7掩盖了内在的SOAP协议,但我希望本文有助于理解SOAP的操作过程。

下面是客户端VB代码:
  VB Client Code
  Sub Main()
  Dim objHTTP As New MSXML.XMLHTTPRequest
  Dim strEnvelope As String
  Dim strReturn As String
  Dim objReturn As New MSXML.DOMDocument
  Dim dblTax As Double
  Dim strQuery As String
  
  @#创建SOAP封装
  strEnvelope = _
   "<soap:envelope xmlns:soap=""urn:schemas-xmlsoap-org:soap.v1"">" & _
   "<soap:header></soap:header>" & _
   "<soap:body>" & _
   "<m:getsalestax xmlns:m=""urn:myserver/soap:TaxCalculator"">" & _
   "<salestotal>100</salestotal>" & _
   "</m:getsalestax>" & _
   "</soap:body>" & _
   "</soap:envelope>"
  
  @#设定发往本地服务器
  objHTTP.open "post", "http://localhost/soap.asp", False
  
  @#设定标准SOAP/ XML格式
  objHTTP.setRequestHeader "Content-Type", "text/xml"
  
  @#设置调用函数头
  objHTTP.setRequestHeader "SOAPMethodName", _
   "urn:myserver/soap:TaxCalculator#GetSalesTax"
  
  @#SOAP呼叫
  objHTTP.send strEnvelope
  
  @#取出返回信封
  strReturn = objHTTP.responseText
  
  @#加载到DOM
  objReturn.loadXML strReturn

原文转自:http://www.ltesting.net