技术开发 频道

简单对象访问协议(SOAP)初级指南

  SOAP体的核心 

  SOAP的XML特性是为把数据类型的实例序列化成XML的编码模式。为了达到这个目的,SOAP不要求使用传统的RPC风格的代理。而是一个SOAP方法调用包含至少两个数据类型:请求和响应。考虑这下面个COM  IDL代码: 

[  uuid(DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA)  ] 
interface  IBank  :  IUnknown  { 
HRESULT  withdraw([in]  long  account, 
[out]  float  *newBalance, 
[in,  out]  float  *amount 
[out,  retval]  VARIANT_BOOL  *overdrawn); 


  在任何RPC协议下,account和amount参数的值将出现在请求消息中,newBalance,overdrawn参数的值,还有amount参数的更新值将出现在响应消息中。 

  SOAP把方法请求和方法响应提升到了一流状态。在SOAP中,请求和响应实际上类型的实例。为了理解一个方法比如IBank::withdraw怎样映射一个SOAP请求和响应类型,考虑下列的数据类型: 

struct  withdraw  { 
long  account; 
float  amount; 
}; 
  
  这是一个所有的请求参数被打包成为一个单一的数据类型。同样下面的数据表示打包所有响应参数到一个单一的数据类型。 

struct  withdrawResponse  { 
float  newBalance; 
float  amount; 
VARIANT_BOOL  overdrawn; 
}; 

  再给出下面的简单的Visual  Basic程序,它使用了以前定义的Ibank接口: 

Dim  bank  as  IBank 
Dim  amount  as  Single 
Dim  newBal  as  Single 
Dim  overdrawn  as  Boolean 
amount  =  100 
Set  bank  =  GetObject("SOAP:http://bofSOAP.com/am";) 
overdrawn  =  bank.withdraw(3512,  amount,  newBal) 

  这里,在发送请求消息之前,参数被序列化成为一个请求对象。同样被响应消息接收到的响应对象被反序列化为参数。一个类似的转变同样发生在调用的服务器端。 

  当通过SOAP调用方法时,请求对象和响应对象被序列化成一种已知的格式。每个SOAP体是一个XML文档,它具有一个显著的称为<Envelope>的根元素。标记名<Envelope>由SOAP  URI  (urn:schemas-xmlSOAP-org:SOAP.v1)来划定范围,所有SOAP专用的元素和属性都是由这个URI来划定范围的。SOAP  Envelope包含一个可选的<Header>元素,紧跟一个必须的<Body>元素。<Body>元素也有一个显著的根元素,它或者是一个请求对象或者是一个响应对象。下面是一个IBank::withdraw请求的编码: 

<SOAP:Envelope 
xmlns:SOAP=''urn:schemas-xmlSOAP-org:SOAP.v1''> 
<SOAP:Body> 
<IBank:withdraw  xmlns:IBank= 
''urn:uuid:DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA''> 
<account>3512</account> 
<amount>100</amount> 
</IBank:withdraw> 
</SOAP:Body> 
</SOAP:Envelope> 
  
  下列响应消息被编码为: 

<SOAP:Envelope 
xmlns:SOAP=''urn:schemas-xmlSOAP-org:SOAP.v1''> 
<SOAP:Body> 
<IBank:withdrawResponse  xmlns:IBank= 
''urn:uuid:DEADF00D-BEAD-BEAD-BEAD-BAABAABAABAA''> 
<newBalance>0</newBalance> 
<amount>5</amount> 
<overdrawn>true</overdrawn> 
</IBank:withdrawResponse> 
</SOAP:Body> 
</SOAP:Envelope> 

  注意[in,  out]参数出现在两个消息中。 
  
  在检查了请求和响应对象的格式后,你可能已经注意到序列化格式通常是: 

<t:typename  xmlns:t=''namespaceuri''>  ; 
<fieldname1>field1value</fieldname1> 
<fieldname2>field2value</fieldname2> 
</t:typename> 

  在请求的情况下,类型是隐式的C风格的结构,它由对应方法中的[in]和[in,  out]参数组成。对响应来说,类型也是隐式的C风格的结构,它由对应方法中的[out]和[in,  out]参数组成。这种每个域对应一个子元素的风格有时被称为元素正规格式(ENF)。一般情况下,SOAP只用XML特性来传达描述包含在元素内容中信息的注释。 

  象DCOM和IIOP一样,SOAP支持协议头扩展。SOAP用可选的<Header>元素来传载被协议扩展所使用的信息。在这种情况下命名causality的头将与请求一起序列化。收到请求后,服务器端软件能查看头的名域URI,并处理它识别出的头扩展。这个头扩展被http://comstuff.com  URI识别,并期待一个如下的对象: 

struct  causality  { 
UUID  id; 
}; 

  在这种情况下的请求,如果头元素的URI不能被识别,头元素可以被安全地忽略。 

  但你不能安全的忽略所有的SOAP体中的头元素。如果一个特定的SOAP头对正确处理消息是很关键的,这个头元素能被用SOAP属性mustUnderstand=’true’标记为必须的。这个属性告诉接收者头元素必须被识别并被处理以确保正确的使用。为了强迫前面causality头成为一个必须的头,消息将被写成如下形式: 

<SOAP:Envelope 
xmlns:SOAP=''urn:schemas-xmlSOAP-org:SOAP.v1''> 
<SOAP:Header> 
<causality 
SOAP:mustUnderstand=''true'' 
xmlns="http://comstuff.com";> 
<id>362099cc-aa46-bae2-5110-99aac9823bff</id> 
</causality> 
</SOAP:Header> 
<!—  SOAP:Body  element  elided  for  clarity  —> 
</SOAP:Envelope> 

  SOAP软件遇到不能识别必须的头元素情况时,必须拒绝这个消息并出示一个错误。如果服务器在一个SOAP请求中发现一个不能识别的必须的头元素,它必须返回一个错误响应并且不发送任何调用到目标对象。如果客户端在一个SOAP请求中发现一个不能识别出的必须的头元素,它必须向调用者返回一个运行时错误。(在COM情况下,这将映射为一个明显的HRESULT) 

0
相关文章