SOAP协议初级指南(5)


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,DCOM,或IIOP代理)看上去象图8中所表示的那样。这里,在发送请求消息之前,参数被序列化成为一个请求对象。同样被响应消息接收到的响应对象被反序列化为参数。一个类似的转变同样发生在调用的服务器端。

  当通过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:uuidSOAP协议初级指南(5) - Alaric - 记录在编程世界里成长的历程EADF00D-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:uuidSOAP协议初级指南(5) - Alaric - 记录在编程世界里成长的历程EADF00D-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>元素来传载被协议扩展所使用的信息。如果客户端的SOAP软件包含要发送头信息,原始的请求将可能如图9所示。在这种情况下命名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)

优质内容筛选与推荐>>
1、OPENVAS运行
2、成人搞笑006
3、vector的内存分配问题
4、get和post的区别
5、Django组件-ModelForm


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号