SOAP较为详细文档

来源:互联网 发布:淘宝帐户绑定手机号码 编辑:程序博客网 时间:2024/06/03 11:43
 
  SOAP
1 其实Web Services 的核心就是SOAP和WSDL,它们隐含于J2EE WebServices平台的通信层于部署层
2 什么是SOAP
SOAP最初是简单对象访问协议(即Simple Object AccessPropotol)的缩写,但它只是个名称而已。SOAP1.1是J2EE WebServices使用的标准消息传递协议,而且通常是Web服务的事实标准。
SOAP的主要应用是应用程序与应用程序之间的通信(A2A),且主要应用于商务对商务(B2B)的通信以及企业应用集成(EAI)。B2B和A2A是同一个问题的2个方面,两者都要解决集成软件应用程序以及共享数据这样的问题。为了使B2B和EAI真正起作用,协议必须是与平台无关,具有灵活性并且基于标准且通用的技术。
        SOAP技术与早期的B2B和EAI技术,如CORBA和EDI(电子文档交换技术)不一样,SOAP能满足这些要求,而且应用广泛,并已得到大多软件企业的支持,如(W3C,WS-I,OASIS)。
        其实SOAP只不过是伴随其使用规则的另一个XML标记语言。SOAP有一个清晰的目标,即通过网络交换数据。它将重点放在了如何封装,编码XML数据以及如何定义用于传输和接收这些数据的规则上了。简单的说,SOAP就是一个网络应用协议。

5为什么SOAP会非常受欢迎
        SOAP定义了如何通过软件以独立于各种编程语言或平台的方式来构造消息,处理消息,从而使那些用于不用编程语言编写的程序之间具有互操作性,并能在不同的操作系统上运行。
        它通过XML命名空间使SOAP具有更强的扩展性。而且它基于XML为基础,并且SOAP它用于HTTP隧道的标准方法。HTTP隧道是将另外一个协议隐藏与HTTP消息中以穿越未收到阻止的防火墙的过程。防火墙通常允许HTTP通过端口80通行,但会禁止或限制使用其他协议或端口。
       SOAP的基本结构
<?xml version=”1.0” encoding=”UTF-8”?>
<soap:Envelope
Xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/>
<soap:Body>
…………………
…………………………
………………….
  </soap:Body>
</soap:Envelope>

SOAP消息与传统邮递服务中使用的信封类似。就像纸信封内包含信件一样,SOAP消息包含了XML数据。

SOAP中根元素为Envelope元素。
Envelope元素可以包含余个可选的Header元素,同时必须包含一个Body元素。
如果用户使用了Header元素,那么该元素必须是Envelope元素的直接子元素。并在Body元素之前。

Header元素以一个或多个不同XML元素的形式包含消息方面的信息,其中每一个元素描述与消息关联的服务的某些方面或质量(服务质量是说-------)

Header元素可以包含各种XML元素,这些XML元素用于描述安全凭证,ID,路由指令,或在Body元素中处理数据时涉及的其他非常重要的消息方面的信息。可以这样说,如果我们希望为每一个SOAP消息附加一个唯一的标识符,用于测试和登陆。虽然唯一标识符不是SOAP协议本身的部分,但用户可以容易的向Herder元素添加标识符,如下例:
<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”
Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “>
  <soap:Header>
      <mi:message-id>2223322332233232:fffff</mi:message>
  </soap:Header>
<soap:Body>
   <!--                   -->
</soap:Body>
</soap:Envelope>

值得注意的是:message-id元素称为文件头,并且该元素是由其自己的命名空间标识的任意XML元素。
又如下面例子,带XML数字签名文件头的SOAP消息
: <?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#>

<soap:Header>
   <mi:message-id>111111111111111111111111111111111:-8000</mi:message>
   <sec:Signature>
      <ds:signature>
          …………………
        ……………….
       </ds:signature>
     </sec:Signature>
</soap:Header>
</soap:Envelope>

也就是说,可以在Header元素中放入任意数量的文件头,而且每个代码快均由合适的对应的函数来处理。。。。

       SOAP命名空间
XML命名空间在SOAP里起着非常重要的作用。因为SOAP可以在Header和Body元素中包含若干不同的XML元素,为了避免冲突,必须使用唯一的命名空间来标识它们。
如下例:
   : <?xml version= “1.0” encoding = “UTF-8” ?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#>

<soap:Header>
   <mi:message-id>111111111111111111111111111111111:-8000</mi:message>
   <sec:Signature>
      <ds:signature>
       </ds:signature>
     </sec:Signature>
</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
     Xmlns:po = http://www.Monson-Haefel.com/jwsbook/po
     Xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance>
   ……………………………………………
   </po:purchaseOrder>

</soap:Body>
</soap:Envelope>
正是因为SOAP使用了XML命名空间,所以使SOAP成为灵活且可扩展的协议。。命名空间完全限定了元素名称或属性名称。。

【注意】在Envelope元素声明的第一个命名空间定义了标准SOAP元素(即Envelop,Header,和Body元素)的命名空间。。。。如:

<soap:Envelope>
<Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”>
</soap:Envelope>
此命名空间确定了所使用的SOAP1.1版本,SOAP消息必须使用Envelope元素的命名空间声明成如下标准的SOAP1.1信封命名空间:
<xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”>
此规则保证了所有确认消息使用完全相同的命名空间和XML模式。。。
Header元素中的每个文件头应有自己的命名空间,这一点非常重要,因为命名空间有帮助SOAP应用程序指定文件头并单独处理它们

SOAP 消息的所有本地元素都必须是命名空间限定的元素(就是SOAP1.1命名空间为前缀),因为SOAP1.1的XML模式将ElementFormDefault属性设置为了”qualified”,此外,Basicprofile1.0要求所有由Body元素包含的应用程序专用的元素必须喂限定元素。
同样可以通过声明xsi:schemaLocation属性来进行有效性检验,但大多数情况下,SOAP堆栈会在设计时处理此问题,并不需要在SOAP消息中显示的声明xsi:schemaLocation。
【解释】所谓的SOAP堆栈使用于处理和传递SOAP消息的代码库。比如,J2EE1.4,Microsoft.NET都用自己的SOAP堆栈,即用于处理SOAP消息的自己的代码库。

【补充】有些SOAP堆栈要大量利用XML模式实例命名空间来说明元素的数据类型(比如:xsi:type=”xsd:float”),可是有些SOAP则不一样。当接收方需要类型化元素但发送方没有类型化元素时,这样的堆栈就会出问题。根据BP,只能用xsi:type属性来表示正在派生的XML类型替换它的基本数据,
对SOAP和应用程序专用的数据使用完全限定的名称会告诉SOAP接收方如何处理消息,以及要采用哪些XML模式来验证内容。。如:
①        文件头中的具体版本差异会影响接受方处理处理消息的方式,所以通过其命名空间指定的文件头版本可以使接收方切换处理模块,或当它不支持的时候拒绝消息。
②        合理的确定Body元素中包含的XML元素的类型可以使SOAP接收方用对应的代码模块处理这些元素,或者当它不支持指定的额命名空间时可能会拒绝消息。

【总结】
可以看出,SOAP消息可以包含许多不同的命名空间,从而使SOAP消息传递更具模块化,此模块化使得SOAP消息的不同部分能够独立于其他部分加以处理,并且能单独进行更改。
也就是说,我们可以不断更改SOAP Envelope或文件头的版本。但Body元素中应用程序专用内容的结构还是保持不变。
   【注意】SOAP消息传递模式的模块化也允许处理SOAP消息的代码模块化
①        处理Envelope元素的代码独立于处理文件头的代码
②        而文件头独立于SOAP Body 元素中处理应用程序专用的数据代码。
③        模块化使用户能够用不同的代码库来处理SOAP消息的不同部分。
       SOAP消息命名空间的特殊性
SOAP消息的命名空间目前为止都是在Envelope中,但并非一定可以这样做。
可以在Header元素或在文件头中声明这些命名空间。命名空间总是局部地确定范围,而且可以在任何级别加以声明,只要讨论的问题位于该范围内即可。如下例:
                     在Header元素中声明命名空间
<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
<soap:Header
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#>
   <mi:message-id>111111111111111111111111111111111:-8000</mi:message>
   <sec:Signature>
      <ds:signature>
       </ds:signature>
     </sec:Signature>
</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
    
   ……………………………………………
   </po:purchaseOrder>

</soap:Body>
</soap:Envelope>
                    在文件头中声明命名空间

<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
<soap:Header>

   <mi:message-id>111111111111111111111111111111111:-8000</mi:message>

   <sec:Signature>
      <ds:signature
                Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#
>
       </ds:signature>
     </sec:Signature>
</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
    
   ……………………………………………
   </po:purchaseOrder>

</soap:Body>
</soap:Envelope>
这里在补充一下的是,虽然要求用前缀来限定Body元素中的应用程序专用的元素,但对包含在Header元素中的元素没有这样额要求。。


下表是WS-I Basic Profile 1.0中使用的命名空间前缀:

前缀        命名空间
Soap        “http://schemas.xmlsoap.org/soap/envelope”
Xsi        “http://www.w3.org/2001/XMLSchema-instance”
Xsd        “http://www.w3.org/2001/XMLSchema”
Soapenc        “http://schemas.xmlsoap.org/soap/encoding/”
Wsdl        “http://schemas.xmlsoap.org/wsdl/”
Soapbind        “http://schemas.xmlsoap.org/wsdl/soap/”
Wsi        “http://ws-i.org/schema/conformanceClaim/”

SOAP头
首先要说明的是SOAP规范(制定者是Microsoft):
          SOAP信封:
                      请求,响应,标识所要应用程序功能点的消息结构。
       SOAP编码方式:
序列化SOAP消息和这些消息中的应用程序定义类型的标准机制
       SOAP RPC表示:
表示远程过程调用的机制

而SOAP头规范定义了一些规则,在消息路径中必须根据这些规则来处理文件头。而消息路径则是SOAP消息从初始发送方到最终接收方的路由。SOAP规则要指定哪些节点必须处理特殊的文件头,以及对文件头进行处理后应该做什么方面的事。
    
SOAP术语介绍:
SOAP与其他应用程序协议不同,SOAP并不显至于单个的消息传递范例,SOAP可以与多种消息传递系统(如同步,异步,RPC,单向等)一起使用,可以用非传统的方式组合它们。而SOAP是用于通过网络在SOAP应用程序间交换消息的协议。所以可以这样理解:
SOAP应用程序只不过是一个用于产生或处理SOAP消息的软件,发送SOAP消息的应用程序称为发送方。接收SOAP消息的应用程序称为接收方。而这些应用程序有时候同时具备这2个功能。
SOAP消息沿消息路径从发送方传递到接收方,所有的SOAP消息起始于初始发送方,并在最终接收方结束。客户这一术语有时指请求消息的初始发送方,而术语Web服务则指请求消息的最终接收方。
消息传递以及运用的概念
当SOAP消息沿消息路径传递时,其头文件可以由任意数量的SOAP中介体解释与处理。
   SOAP中介体既可以是接收方也可以使发送方,,它可以接收SOAP消息,处理一个或多个文件头,并将SOAP消息传送到另外一个SOAP应用程序,沿消息路径(初始发送方,中介体,最终接收方)的各应用程序也称为SOAP节点

我希望通过一个例子来解释消息路径中的节点如何处理文件头。我们假设有2个相对简单的文件头Message-id和Processed-by。文件头Message-id用于记录SOAP应用程序(即节点),这些SOAP应用程序要沿着从初始发送方到最终接收方这一传递路径处理SOAP消息。
与Message-id文件头类似,Processed-by文件头用于调试程序与记录。
下例中,SOAP消息在到达最终接收方之前要通过若干个中接替传递。我来说说中介体以等的概念吧:
  假设SOAP消息的初始发送方是一个客户节点,最终接收方是一个运输节点,那么中间会经过一些必要的途径,比如:销售节点,应付款节点,库存节点,最后到运输节点。
从初始发送放到最终接受方中间所经过的一系列的节点,我们称为中介体。它们也会传送SOAP消息到下一个中介体。
还要在强调一个概念的是:位于SOAP消息路径中的各个中介体不能修改SOAPBody元素中的应用程序专用内容,但可以处理SOAP头文件,而且经常这么做。
在下面的例子中,要求每个SOAP中介体向Processed-by文件头添加一个Note元素,以标识其本身并确定其处理消息的时间。程序在五个应用程序均向Processed-by文件头添加Node元素之后的消息。
<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#
Xmlns:proc=”http://www.Monson-Haefel.com/jwsbook/processed-by”>

<soap:Header>
   <proc:processed-by>

<!—下面出现了5个节点。分别向Processed-by添加Node元素之后的消息-->
        <node>
           <time-in-millis>10136123146231</time-in-millis>
           <identity>http://www.customer.com</identity>
        </node>

        <node>
           <time-in-millis>101345416231</time-in-millis>
           <identity>http://www.Monson-Haefel.com</identity>
                </node>
<node>
           <time-in-millis>1035345234231</time-in-millis>
           <identity> http://www.Monson-Haefel.com</identity>
        </node>
<node>
           <time-in-millis>156564346231</time-in-millis>
           <identity> http://www.Monson-Haefel.com</identity>
        </node>
<node>
           <time-in-millis>103423454</time-in-millis>
           <identity> http://www.Monson-Haefel.com</identity>
        </node>

</proc:processed-by>
</soap:Header>

<soap:Body>
   <!—Application –Specific data goesHere-->
</soap:Body>
</soap:Envelope>
此例,当处理文件头时,每个节点在将SOAP消息传递到下一个接收方之前进行从SOAP消息读文件头,对文件头进行处理,然后删除文件头这样的操作。但消息路径中的节点如何知道它要处理哪一个文件头呢?
  SOAP1.1应用程序用actor属性来识别用于处理指定文件头的节点。还用mustUnderstand属性表示处理头的节点是否能够识别文件头以及知道如何处理它。
Actor属性
Actor属性由SOAP1.1注释定义,它是SOAP的Envelope,Body,和Header元素的命名空间(即Http://schemas,xmlsoap.org/soap/envelop/)的一部分。
   我们可以使用Actor属性指定具体节点所完成的功能、

Actor属性使用一个URI标识节点处理对应的文件头时必须扮演的角色。当一个节点接收到一个SOAP消息时,它要分析每一个文件头,以确定哪些代码块是由该节点所支持的加色(我在这里说一下,其实Actor这个属性就可以看成一个人,他在这个社会中会扮演很多的角色,比如:父亲 儿子 丈夫医生,同样,Actor也是如此)
Actor属性与XML命名空间组合在一起使用,以确定要用哪一个代码模块处理具体的文件头。因此,接收节点首先要根据文件头的命名空间确定它是否起Actor属性所指定的角色。
然后选择对应的代码模块来处理这些文件头。。。
   所以,接收节点必须承认由赋予文件头的Actor属性所指定的角色,同时还要承认与文件头对应的XML命名空间。。
一个节点可以由对一个消息进行操作的多个模块,所以它会由多个角色。这样的话,我们可以使用若干个不同的角色来标识消息路径中的每一个节点。
如下例:()
                                1-1例
<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#
Xmlns:proc=”http://www.Monson-Haefel.com/jwsbook/processed-by”>

<soap:Header>
   <mi:message-idsoap:actor=”http://www.Monson-Haefel.com/logger”>
111111111111111111111111111111111:-8000
</mi:message>
   <sec:Signature>
      <ds:signature>
       </ds:signature>
     </sec:Signature>
</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
   ……………………………………………
   </po:purchaseOrder>
</soap:Body>
</soap:Envelope>
此例子,在消息路径中,只有用了Actor属性值http://www.Monson-Haefel.com/logger标识了的节点才能处理Message-id文件头,其他节点会忽略该文件头。

【注意】除了像Http://www.Monson-Haefel.com/logger这样的客户URI之外,SOAP还为actor属性标识了2个标准角色,即Next和Ultimatereceiver角色,这两个标准角色标识应该处理文件头的各节点,而且它们具有较好的自释性
                Next   和   Ultimate receiver 角色
Next角色表示消息路径中的下一个节点必须处理文件头。Next角色有一个指定的URI,即http://schemas.xmlsoap.org/soap/actor/next,此URI必须作为actor属性的值
Ultimate receiver角色表示只有消息的最终接受方才能处理文件头。协议并没有为此提供明显的URI。。
如果某一角色在文件头中没有actor属性,那么表示该角色是ultimate receiver
我们先来看一个例子: 如下1-2例:
1-2例
<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#
Xmlns:proc=”http://www.Monson-Haefel.com/jwsbook/processed-by”>

<soap:Header>
   <mi:message-idsoap:actor=”http://www.Monson-Haefel.com/logger”>
111111111111111111111111111111111:-8000
</mi:message>
<proc:processed-by
Soap:actor=”Http://schemas.xmlsoap.org/soap/actor/next”>
   <note>
      <time-in-millis>132132156231</time-in-millis>
      <identity>http://www.customer.com/</identity>
    <note>
         </proc:processed-by>
   <sec:Signature>
      <ds:signature>
       </ds:signature>
     </sec:Signature>
</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
   ……………………………………………
   </po:purchaseOrder>
</soap:Body>
</soap:Envelope>
【重 点】本例中,此消息路径的下一个接收方无论提供其他何种服务,都应该处理Processed-by文件头。当节点处理文件头时,它必须从SOAP消息中删除该文件头。节点也可以向消息添加新的文件头。SOAP节点通常通过修改文件头来假装的删除它(在逻辑上与删除,修改,然后再将文件头添加回SOAP消息一样)。这一点小小的技巧使节点传播文件头时能够遵循SOAP规范,不会丢失数据。
比如1-1例中,节点可以删除Message-id文件头,但用户并不希望删除1-2例子中的processed-by文件头,因为希望消息路径中的所有节点都能向他添加信息。,因此1-1例中节点要向processed-by文件头添加自己的数据,然后将SOAP消息传递消息路径中的下一个节点。让我们看看例子1-3吧,其实它已经删除了message-id文件头,并且修改了processed-by文件头
1-3 例子

<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#
Xmlns:proc=”http://www.Monson-Haefel.com/jwsbook/processed-by”>

<soap:Header>
  
<proc:processed-by
Soap:actor=”Http://schemas.xmlsoap.org/soap/actor/next”>
   <note>
      <time-in-millis>132132156231</time-in-millis>
      <identity>http://www.customer.com/</identity>
    <note>

   <note>
      <time-in-millis>132132156231</time-in-millis>
      <identity>http://www.customer.com/</identity>
    <note>

         </proc:processed-by>
   <sec:Signature>
      <ds:signature>
       </ds:signature>
     </sec:Signature>
</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
   ……………………………………………
   </po:purchaseOrder>
</soap:Body>
</soap:Envelope>
mustUnderstand属性
使用next标准角色类型会有一些后遗症。在许多情况下,用户可能并不知道确切的消息路径或不知道消息路径中的各节点的功能,即用户并不总能知道各节点是否正确地处理文件头。例如:processed-by文件头所指向的next角色,表示它下一个节点应该处理该代码块,但如果下一个节点不能识别该文件头的话,就会出问题了。
  文件头必须用mustUnderstand属性来表示处理是否为强制性处理。mustUnderstand属性由SOAP1.1命名空间http://schemas.xmlsoap.org/soap/envelop定义,该属性的值可以是“1“0”分别代表真和假。该属性默认为“0”。
MustUnderstand属性名中的Understand表示节点必须能够根据其XML结构和命名空间识别文件头,并知道如何处理它。换句话说:【这个是我自己总结的,如果节点扮演了由文件头的actor属性表示的角色,但没有写代码来处理文件头,那么就不会识别该文件头】
如果用户添加了中间节点但没考虑指向它的所有可能的文件头,或没有考虑next角色,那么就会产生一个SOAP异常【SOAP异常下面才讲到】,并放弃处理该消息,也就不能给下一个节点提供消息了。
1-4例子

<?xml version = “1.0” encoding = “UTF-8”?>
<soap:Envelope>
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”

Xmlns:mi=”http://www.Monson-Haefel.com/jwsbook/message-id “

Xmlns:sec=http://schemas.xmlsoap.org/soap/security/2000-12

Xmlns:ds=http://w3c.org/2000/09/xmldsig#
Xmlns:proc=”http://www.Monson-Haefel.com/jwsbook/processed-by”>

<soap:Header>
  <proc:processed-by
Soap:actor=http://schemas.xmlsoap.org/soap/actor/next
Soap:mustUnderstand=”1”>
<note>
      <time-in-millis>132132156231</time-in-millis>
      <identity>http://www.customer.com/</identity>
<note>

<note>
      <time-in-millis>132132156231</time-in-millis>
      <identity>http://www.customer.com/</identity>
<note>
</proc:processed-by>


</soap:Header>

<soap:Body sec:id=”Body”>
  <po:purchaseOrder orderDate=”2003-09-22”
   ……………………………………………
   </po:purchaseOrder>
</soap:Body>
</soap:Envelope>
【补充】如果您要添加一个新的节点的话,那么该节点也要处理发送过来的SOAP消息。假设当添加的新的节点,编程人员忘记包含处理processed-by文件头的逻辑了,因此新的节点不能识别processed-by文件头,并且不知道如何处理它。又由于mustUnderstand属性设置为“1”,所以新的节点不得不抛弃SOAP消息,产生一个SOAP异常,并且返回给发送方。。。。。
如果SOAP接收方无法识别强制性文件头,那么会要求它用错误代码mustUnderstand产生一个错误(稍后介绍)
传递模式与SOAP消息
是否将错误传递回发送方取决于消息传递交换模式(MEP)是单项还是请求、响应模式。如果SOAP应用程序使用了请求、响应消息传递交互模式,则要求将SOAP错误消息传递回发送方。如果SOAP应用程序使用的是单向消息传递模式,那么则不需要返回传递错误消息。
如果MustUnderstand属性的值为0,那么SOAP指定的处理要求则不一样。如果一个节点要完成由非强制性文件头申明的角色,而且某一应用程序没能识别该文件头(没能识别出XMK结构或命名空间),那么它必须删除该文件头。而且,并获没有强迫它去进行处理,也没有迫使它抛弃消息。可以随意删除文件头并将消息沿消息路径传递到下一个节点。
【推荐】
接收方不应该拒绝消息,应为还没有处理(和删除)指向其它某个节点的文件头。换句话说,接收方不应该试图根据目前有哪些文件头来确定路径中位于前面的节点是否成功的处理了消息。此规则特别适用于最终接受方,最终接受方不应该拒绝消息,因为从来不回处理用于某些未知角色的文件头。
如果接收方分局并未指向的文件头的状态开始分析并且拒绝消息,则不可能在更改消息路径是不考虑这些更改对下游造成的连锁反应,由于要求各节点“考虑其自己的业务”,因此消息路径可以变化,而且是很动态的。添加一个新的中介体(或删除它)并不需要调整消息路径中的其他各节点。
WS-I 一致性文件头
虽然BP没有涉及到特殊类型的文件头,但它确实指定了一个表示SOAP晓得遵循BP的可选一致性文件头。如1-6例:
1-6
<?xml version=”1.0”encoding=”UTF-8”>
<soap:Envelope
Xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope”>
<soap:Header>
   <wsi:ClaimconformsTo=http://ws-i.org/profiles/basic/1.0
Xmlns:wsi=http://ws-i.org/schemas/conformanceClaim/>
</soap:Header>
<soap:Body sec:id=”Body”>
………………………..
</soap:Body >
</soap:Envelope>

WS-I BasicProfile指出并不需要Claim文件头,它还规定“不能将消息中缺少一致性声明最为消息是否符合一个或多个配置文件的判断”
  SOAP消息可以为它遵循的每一个配置文件声明一个单独的Claim文件头。
Claim元素只能作为Header元素的直接子元素来声明,它不能出现在SOAP消息的其他任何部分。此外,Claim文件头总是可选的,因此它的MustUnderstand属性值不能为“1”,用户不能要求接收方处理Claim文件头
【关于文件头的进一步说明】
SOAP文件头是扩展SOAP协议的一个功能非常强大的措施。对开发人员和开发商来说,SOAP文件头作为元数据的一中结构,使用起来要比采用其他协议中的类似机制(比如CORBA  IIOP中的“服务上下文”)更加灵活和更为容易。
Message-id和processed-by文件头知识创建的自己的定制的文件头,各社团通常会定义一般用途的SOAP文件头。这些机构主要是考虑的是强调服务质量的文件头,比如安全性,事务,消息持续性以及路由。
BP并没有强调这些潜在标准,但WS-I最终将创建更为高级的配置文件,该文件能够将在OASIS,W3C,Microsoft,IBM,以及其他机构中使用的许多协议组合成一起。

第二章 SOAP体
【重要的概念】
虽然Header元素是可选元素,但所有SOAP消息必须包含一个Body元素。Body元素要包含应用程序专用的数据或者错误消息。应用程序专用的数据是用户希望与Web服务进行交换的信息,它可以是任意XML数据或是提供给过程调用的任意参数。不论是哪一个数据,Body元素应包含正在交换的应用程序数据。只有错误发生时才会使用错误消息。发现了问题(如处理错误或消息构造不合适)的接收节点会将问题传递回消息路径中位于该节点之前的发送方。SOAP消息可以携带应用程序专用的数据或错误,但不能通用时携带两者。
   无论Body元素包含的是应用程序专用的数据还是错误,大多数SOAP专家认为只有SOAP消息的最终接送方才应该处理Body元素的内容。消息路径中的中介点可以浏览Body元素,但不应该以任意方式改变内容,这一点与文件头不相同。
   沿消息路径的各中介体均能处理文件头,但只有最终接收方才应该更改Body元素内容,这以点非常重要。

【SOAP消息传递模式】
   第一:Document/Literal消息传递模式
     在Document/Literal消息传递模式中,SOAP的Body元素包含一个XML文档段,该文档段是以个良好的XML元素,它包含独立于SOAP消息的属于XML模式和命名空间的任意应用程序数据。
   第二:RPC/Literal消息传递模式
     RPC/Literal消息传递模式可以使用SOAP消息对过程调用或对带参数和返回值的方法调用建立模型。在RPC/Literal消息传递模式中,总是将Body元素的内容格式化为Struts。RPC请求消息包含调用的方法名称与输入参数。
RPC响应消息则包含了返回值和各种输出参数(或错误)。
在许多情况下,RPC/Literal消息传递模式用于以传统组建的形式提供Web服务。传统组件可以是Servlet,无状态会话Bean,javaRMI对象,CORBA对象或DCOM组件。这些组件不会显式改变XML数据,但它们均有带参数和返回值的方法。
比如2-1例子:
Package   com.jwsbook.soap;
Import java.rmi.RemoteException;

Public interface BookQipte extends java.rmi.Remote{
    //Get thewhilesale price of a book
    Public floatgetBookPrice(String ISBN) throwsRemoteException,InvalidISBNException;
}
此例有一个名为BookQuote且使用JAX-RPC(一个J2EE WebServices端点),而且是BookQuote的远程借口。
getBookPrice()方法以ISBN(International Standard BookNumber,国际标准书号)形式声明了一个参数,该参数付给每一个唯一的字符。当用户用对应的ISBN激活该方法时,Web服务返回信息。
   此JAX-RPC服务端点可以使用RPC/Literal消息传递模式,Web服务使用了2个SOAP消息,即一个请求消息和一个应答消息。请求消息是从初始发送方向Web服务传递,并包含方法名getBookPrice和ISBN字符串参数。
  应答消息要传递回初始发送方,并以Float值的形式包含了信息。
下面2-2用于BookQuote Web服务的SOAP请求消息
<?xml version=”1.0”encoding=”UTF-8”>
<soap:Envelope
Xmlns:soap=http://schemas.xmlsoap.org/soap/enevlope
Xmlns:mh=”http://www.Monson-Haefel.com/jwsbook/BookQuote”>
  <soap:Body>
                <mh:getBookPrice>
                        <isbn>03030201</isbn>
                </mh:getBookPrice>
         </soap:Body>
</soap:Envelope>

例子2-3对2-2给出了对应的响应消息

<?xml version=”1.0”encoding=”UTF-8”>
<soap:Envelope
Xmlns:soap=http://schemas.xmlsoap.org/soap/enevlope
Xmlns:mh=”http://www.Monson-Haefel.com/jwsbook/BookQuote”>
  <soap:Body>
                <mh:getBookPrice>
                        <result>24.99</result>
                </mh:getBookPrice>
         </soap:Body>
</soap:Envelope>

RPC/Literal消息传递模式与Document/Literal消息传递不同。Document/Literal消息传递模式不会假设在消息的Body元素内所包含元素的类型与结构(但文档要遵循一些XML模式)。RPC/Literal消息传递模式要携带一些简单的参数。RPC样式的消息传递是分布式技术中最常用的方式,其中包括EJB,CORBA,DCOM等。
   所以,SOAP为RPC样式的消息传递定义了一个标准的XML格式,即RPC/Literal传递。
RPC/Literal消息传递模式指定了在SOAP消息中的Body元素中表示方法以及它们的参数的方式。
   重要的是要知道RPC/Literal和Document/Literal消息传递模式与使用像JAX-RPC这样的工具的开发人员的观点可能有所区别,因为JAX-RPC可以为RPC/Literal和Document/literal提供过程调用语义。
   有些人对RPC/Literal模式的有效性提出了疑问:当能够使用Document/Literal模式时,为什么还要使用RPC/Literal模式呢??毫无疑问,某些时候Document/Literal模式更为简单,而且使用Document/Literal模式还可以采用XML模式检验。这些只有等待BP来涉及了。
消息传递模式与消息传递交换模式
我们会很容易把RPC/Literal与Document/Literal模式与单向和请求/响应消息交换模式(MEP)弄混,但两者的概念截然不同。
   当我们说消息传递模式是RPC/Literal或Document/Literal模式时,通常描述的是SOAP消息的有效负载:即XML文档段或者是与远程过程调用对应的参数和返回值的XML表示。
与此相反,单向和请求/响应消息交换模式表示消息的流向,而不是消息的内容。
   单向消息传递是单方向传递,而请求/响应消息传递则是双向传递。

其他的信息传递模式
  我这里就不说其他的信息传递模式了,因为RPC/Literal和Document/Literal模式已经过时了,而且BP坚决反对使用这2种模式,而且它们会引起一切互操作性问题。感兴趣的朋友可以在网上搜索这2个模式的详细信息

原创粉丝点击