PHP SOAP详解
1. SOAP简介
1.1应用背景
对于应用程序开发来说,使程序之间进行因特网通信是很重要的。目前的应用程序通过使用远程过程调用(RPC)在诸如 DCOM 与 CORBA 等对象之间进行通信,但是 HTTP 不是为此设计的。RPC 会产生兼容性以及安全问题;防火墙和代理服务器通常会阻止此类流量。通过 HTTP 在应用程序间通信是更好的方法,因为 HTTP 得到了所有的因特网浏览器及服务器的支持。SOAP 就是被创造出来完成这个任务的。SOAP 提供了一种标准的方法,使得运行在不同的操作系统并使用不同的技术和编程语言的应用程序可以互相进行通信。
1.2概念定义
SOAP 是基于 XML 的简易协议,是用在分散或分布的环境中交换信息的简单的协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。包括三个部分:封装定义了一个描述消息中包含什么内容以及如何处理它们的框架,编码规则用于表示应用程序定义的数据类型的实例,另外还有一个表示远程过程调用和应答的协定。SOAP被设计为可以与各种其它协议结合使用;这里仅描述如何将SOAP和HTTP及HTTP扩展框架相结合。
SOAP以XML形式提供了一个简单、轻量的用于在分散或分布环境中交换结构化和类型化信息的机制。SOAP本身并没有定义任何应用程序语义,如编程模型或特定语义的实现;实际上它通过提供一个有标准组件的包模型和在模块中编码数据的机制,定义了一个简单的表示应用程序语义的机制。这使SOAP能够被用于从消息传递到RPC的各种系统。 目前最新版本的SOAP1.2是Sun Microsystems、IBM、BEA、Microsoft和Oracle等供应商领导的W3C XML工作组推出并维护的。
SOAP的两个目标是简单性和可扩展性,这就意味着有一些传统的消息系统或分布式对象系统中的某些性质将不是SOAP规范的一部分。SOAP是一种分布式计算中的技术,它被有意的设计为轻量级的协议,它的某些功能和其他一些机制(如RMI)共有的,但也存在许多不同的功能,如不支持通过引用传递对象、对象激活、消息批处理等。SOAP也被设计成可扩展的,而简单性和可扩展性意味着SOAP的使用不包含任何特定的编程模式,给定实现的语义是极为灵活的。
SOAP基于XML语言和XSD标准,其定义了一套编码规则,该规则定义如何将数据表示为消息,以及怎样通过HTTP协议来传输SOAP消息,它由以下四部分组成:
> SOAP信封(Envelope):定义了一个框架,该框架描述了消息中的内容是什么,包括消息的内容、发送者、接收者、处理者以及如何处理这些消息。
> SOAP编码规则:它定义了一种系列化机制,用于交换应用程序所定义的数据类型的实例。
> SOAP RPC表示:它定义了用于表示远程过程调用和应答协定。
> SOAP绑定:它定义了一种使用底层传输协议来完成在节点间交换SOAP信封的约定。
SOAP消息基本上是从发送端到接收端的单向传输,它们常常结合起来执行类似于请求/应答的模式。不需要吧SOAP消息绑定到特定的协议,SOAP可以运行在任何其他传输协议(HTTP、SMTP、FTP等)上。另外,SOAP提供了标准的RPC方法来调用Web Service以请求/响应模式运行。
注意:
实际上,SOAP在这里有点用词不当:它意味着下面的Web service是以对象的方式表示的,但事实并不一定如此:你完全可以把你的Web service写成一系列的C函数,并仍然使用SOAP进行调用
2. 消息交换模型
2.1SOAP接点
SOAP结点表示SOAP消息路径的逻辑实体,用于进行消息路由或处理。SOAP结点可以是SOAP消息的发送者、接收方、消息中介。
在SOAP消息模型中,中间方为一种SOAP结点,负责提供发送消息的应用程序和接收方间的消息交换和协议路由功能。中间方结点驻留在发送结点和接收结点之间,负责处理SOAP消息头中定义的部分消息。SOAP发送方和接收方之间可以有0个或多个SOAP中间方,它为SOAP接收方提供分布式处理机制。
一般,SOAP消息中间方分为两种:
1. 转发中间方:这一类型的中间方通过在所转发消息的SOAP消息头块中描述和构造语义和规则,从而实现消息处理。
2. 活动中间方:这一类型的中间方利用一组功能为接收方结点修改外部绑定消息,从而提供更多的消息处理操作。
在SOAP消息交换路径中,借助于SOAP中间方,使得分布式处理模型在SOAP消息交换中得以实现。通过使用SOAP中间方,可以向SOAP应用程序中集成各种功能(如转发、过滤、事务、安全、日志记录、智能路由等)。
2.2没有消息提供者的客户端
不使用消息提供者的应用程序只能交换同步消息。也就是说,扮演客户端角色的应用程序只能发送请求-响应消息。这种类型的客户端采用SAAJ API的SOAPConnection方法。下图演示了在没有消息提供者的情况下,同步消息如何在发送者和接收者之间交换。
图1 不使用消息提供者的SOAP消息
不使用消息提供者的客户端具有以下优点:
> 可以采用J2SE平台编写应用程序。
> 不需要在servlet或J2EE容器中部署应用程序。
> 不需要配置消息提供者。
不使用消息提供者的客户端具有以下局限性:
> 客户端只能发送请求-响应消息
> 客户端只能扮演客户端角色
2.3使用消息提供者的客户端
如果想要获得并且保存在任何时间发送给你的请求,你必须使用消息提供者。使用消息提供者的客户端还能发送异步消息JAXM API提供了使用消息提供者发送和接收消息的框架。你需要在容器中运行客户端,容器提供了消息基础结构让提供者使用。下图演示了在使用消息提供者的情况下,异步消息如何在发送者和接收者之间交换。
图2使用消息提供者的SOAP消息
使用消息提供者的客户端具有以下优点:
> 客户端能够扮演客户端或者服务角色
> 客户端能够切换消息传递给提供者
> 在客户端传递消息到最终接收者之前,它能够发送消息到一个或多个目的地。这些中间的消息接收者被称为actor,它们在消息的SOAPHeader对象中被指定。
> 客户端能够利用任何提供者支持的SOAP消息协议和影响消息类型与可靠性的‘服务质量’,以及消息传递服务的质量。
注意
Sun Java System Application Server包含了一个示例JAXM提供者,它演示了如何使用提供者为发送客户端激活“发后不理(fire and forget)”消息。请察看示例文档获取关于如何激活、部署和使用它的全面信息。示例应用程序可以从以下位置得到:
install_dir/samples/webservices/jaxm/jaxm-provider/
Sun Java System Application Server的未来版本将会包括支持可靠SOAP消息和ebXML消息的JAXM提供者。
3.SOAP消息
3.1SOAP消息的组成部分
所有的SOAP消息都使用XML编码,一条SOAP消息就是一个普通的XML文档,该文档包括下列元素。
> Envelope(信封)元素,必选,可把此XML文档标识为一条SOAP消息。
> Header(报头)元素,可选,包含头部信息(包含了使消息在到达最终目的地之前,能够被路由到一个或多个中间节点的信息)。
> Body(主体)元素,必选,包含所有的调用和响应信息。
> Fault元素,位于Body内,可选,提供有关处理此消息所发生错误的信息。
> Attachment(附件)元素,可选,可通过添加一个或多个附件扩展SOAP消息。
图3 SOAP消息的结构和组成部分
SOAPMessage对象包括:
一个SOAPPart对象,其中包括
一个SOAPEnvelope对象,其中包括
一个空的SOAPHeader对象 – 可选,包括它是为了方便,因为大多数消息都要用到它, SOAP头提供了向SOAP消息中添加关于这条SOAP消息的某些要素(feature)的机制。SOAP定义了少量的属性用来表明这项要素(feature)是否可选以及由谁来处理。
一个空的SOAPBody对象 -包含消息的最终接收者想要的信息的容器,可以容纳消息的内容,还能容纳包含了状态信息或者消息故障明细的错误消息。
AttachmentPart可能容纳普通文本或者图像文件。
SOAPEnvelope是代表消息的XML文件的根元素。它为消息如何处理、由谁处理定义了框架。XML内容从SOAPEnvelope开始。
SOAPHeader是添加特性到SOAP消息的基本机制。它可以容纳任意数目的扩展了基础协议的子元素。例如,header子元素可能会定义认证信息、事务信息、本地信息、等等。处理消息的软件可以在没有事先约定的情况下,使用这个机制定义谁应该处理某个特性,以及该特性是强制的还是可选的。
SOAPBody是发给消息最终接收者的强制信息的容器。SOAP消息还可以容纳一个附件,它不一定非得是XML文件。
3.2SOAP消息举例
先来看一个简单的例子:
在这个例子中,GetLastTradePrice SOAP 请求被发往 StockQuote服务。这个请求携带一个字符串参数ticker符号,在SOAP应答中返回一个浮点数。XML名域用来区分SOAP标志符和应用程序特定的标志符。这个例子说明了在第6节中定义的HTTP绑定。如果SOAP中管理XML负载的规则完全独立于HTTP是没有意义的,因为事实上该负载是由HTTP携带的。
例1 在HTTP请求中嵌入SOAP消息
POST /StockQuote HTTP/1.1
Host:
www.stockquoteserver.com
Content-Type: text/xml;
charset="utf-8"
Content-Length: nnnn
SOAPAction:
"Some-URI"
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<m:GetLastTradePrice xmlns:m="Some-URI">
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
下面是一条应答消息,包括HTTP消息,SOAP消息是其具体内容:
例2 在HTTP应答中嵌入SOAP消息
HTTP/1.1 200 OK
Content-Type: text/xml;
charset="utf-8"
Content-Length:
nnnn
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<SOAP-ENV:Body>
<m:GetLastTradePriceResponse xmlns:m="Some-URI">
<Price>34.5</Price>
</m:GetLastTradePriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP虽然是XML文档,但其编写需要满足如下语法规则:
> SOAP消息必须用XML来编码。
> SOAP消息必须用SOAP Envelope命名空间。
> SOAP消息必须用SOAP Encoding命名空间。
> SOAP消息不能包含DTD引用。
> SOAP消息不能包含XML处理指令。
3.3SOAP Envelope
SOAP Envelope 是SOAP消息结构的主要容器,也是SOAP消息的根元素,它必须出现在每个SOAP消息中,用于把此XML文档标示为一条SOAP消息。
在SOAP中,使用XML命名空间将SOAP标示符与应用程序特定的标示符区分开,将SOAP消息的元素的作用域限制在一个特定的领域。
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
Soap-env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
</ soap-env:Envelope >
以上命名空间都是按照SOAP1.1规范书写,SOAP消息中所有元素必须由第一个命名空间进行限定,SOAP的encodingStyle属性用于定义在文档中使用的数据类型。此属性可出现在任何SOAP元素中,并会被应用到元素的内容及元素的所有子元素上。
对于SOAP1.2规范,对应的命名空间及空信封如下:
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding”>
</ soap:Envelope >
3.4SOAP Header
SOAP Header元素应当作为SOAPEnvelope的第一个直接子元素,它必须使用有效的命名空间。Header还可以包含0个或多个可选的子元素,这些子元素称为Header项,所有的Header项都必须是完整修饰的,即必须由一个命名空间URI和局部名组成,不允许没有命名空间修饰的Header项存在。
Header元素用于与消息一起传输附加消息,如身份验证或事务信息。Header元素也可以包含某些属性。SOAP在默认的命名空间中定义了三个属性:actor,mustUnderstand以及encodingStyle。这些被定义在SOAP头部的属性可通知容器如何对SOAP消息进行处理。
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
Soap-env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap-env:Header>
<auth:UserID xmlns:auth=”some-URI”>
Admin
</auth:UserID>
</soap-env:Header>
</ soap-env:Envelope >
定义了新命名空间的附加元素,元素名(UserID)表明它包含身份验证信息。
3.5SOAP Body
SOAP消息的Body块可以包含以下任何元素:
> RPC方法及其参数
> 目标应用程序(消息接收者)专用数据
> 报告故障和状态消息的SOAP Fault
所有Body元素的直接子元素都称为Body项,Body项必须由命名空间修饰。
如下,该主体表示用于从“www.fruit.com”获取Apples的价格信息的RPC调用。
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
Soap-env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap-env:Body>
<m:GetPrice xmlns:m=”http://www.fruit.com/prices”>
<m:Item>Apples</m:Item>
</ m:GetPrice >
</soap-env:Body>
</ soap-env:Envelope >
命名空间http://www.fruit.com/prices是应用程序专用的元素,它们并不是SOAP标准的一部分。下面是对上述请求的响应:
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
Soap-env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap-env:Body>
<m:GetPriceResponse xmlns:m=”http://www.fruit.com/prices”>
<m:Price>3.2</m:Price>
</ m:GetPriceResponse >
</soap-env:Body>
</ soap-env:Envelope >
3.6SOAP Fault
子元素 |
描述 |
<faultcode> |
供识别故障的代码 |
<faultstring> |
可供人阅读的有关故障的说明 |
<faultactor> |
有关是谁引发故障的信息 |
<detail> |
存留涉及 Body 元素的应用程序专用错误信息 |
SOAP Fault元素用于在SOAP消息中传输错误及状态信息。如果SOAP消息需要包括SOAP Fault元素,它必须作为一个Body项出现,而且至多出现一次。SOAP Fault包括以下子元素:faultcode,faultstring,faultactor,detail.
在下面定义的 faultcode 值必须用于描述错误时的 faultcode 元素中
错误 |
描述 |
VersionMismatch |
SOAP Envelope 元素的无效命名空间被发现 |
MustUnderstand |
Header 元素的一个直接子元素 (带有设置为 "1" 的 mustUnderstand 属性)无法被理解。 |
Client |
消息被不正确地构成,或包含了不正确的信息。 |
Server |
服务器有问题,因此无法处理进行下去。 |
3.7附件
按照SOAP1.1规范的规定,SOAP消息可以包含XML格式的主SOAP信封,以及包含ASCII或二进制等任何数据格式的SOAP附件。如果SOAP消息包含附件,那么SOAP消息将是一个MIME编码的消息,它包含SOAP内容和一个或多个其他类型的附件。因此SOAP消息实际上分为以下两种类型:
> 仅包含XML内容的消息
> MIME编码的消息,包含初始的XML有效内容以及任何数量的附件。这些附件可以是任何其他类型的数据。
【MIME:Multi-purpose Internet Mail Extensions多用途Internet邮件扩展,是一组技术规范,其目的是使用不同字符集来传递文本,也可以在计算机之间传递各种各样的多媒体数据】
4.SOAP HTTP Binding
4.1HTTP 协议
HTTP 在 TCP/IP 之上进行通信。HTTP 客户机使用 TCP 连接到 HTTP 服务器。在建立连接之后,客户机可向服务器发送 HTTP 请求消息:
POST /item HTTP/1.1
Host: 189.123.145.239
Content-Type: text/plain
Content-Length: 200
随后服务器会处理此请求,然后向客户机发送一个 HTTP 响应。此响应包含了可指示请求状态的状态代码:
200 OK
Content-Type: text/plain
Content-Length: 200
在上面的例子中,服务器返回了一个 200 的状态代码。这是 HTTP 的标准成功代码。
假如服务器无法对请求进行解码,它可能会返回类似这样的信息:
400 Bad Request
Content-Length: 0
4.2SOAP HTTP Binding
SOAP 方法指的是遵守 SOAP 编码规则的 HTTP 请求/响应。
HTTP + XML = SOAP
SOAP 请求可能是 HTTP POST 或 HTTP GET 请求。
HTTP POST 请求规定至少两个 HTTP 头:Content-Type 和 Content-Length。
Content-Type
SOAP 的请求和响应的 Content-Type 头可定义消息的 MIME 类型,以及用于请求或响应的 XML 主体的字符编码(可选)。
语法
Content-Type: MIMEType; charset=character-encoding
例子
POST /item HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Content-Length
SOAP 的请求和响应的 Content-Length 头规定请求或响应主体的字节数。
语法
Content-Length: bytes
例子
POST /item HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 250