资源描述
Web Service概述
Web Service的定义
W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计。Web Service服务通常被定义为一组模块化的API,它们可以通过网络进行调用,来执行远程系统的请求服务。
这里我们从一个程序员的视角来观察web service。在传统的程序编码中,存在这各种的函数方法调用。通常,我们知道一个程序模块M中的方法A,向其发出调用请求,并传入A方法需要的参数P,方法A执行完毕后,返回处理结果R。这种函数或方法调用通常发生在同一台机器上的同一程序语言环境下。现在的我们需要一种能够在不同计算机间的不同语言编写的应用程序系统中,通过网络通讯实现函数和方法调用的能力,而Web service正是应这种需求而诞生的。
最普遍的一种说法就是,Web Service = SOAP + HTTP + WSDL。其中,SOAP Simple Object Access Protocol)协议是web service的主体,它通过HTTP或者SMTP等应用层协议进行通讯,自身使用XML文件来描述程序的函数方法和参数信息,从而完成不同主机的异构系统间的计算服务处理。这里的WSDL(Web Services Description Language)web 服务描述语言也是一个XML文档,它通过HTTP向公众发布,公告客户端程序关于某个具体的 Web service服务的URL信息、方法的命名,参数,返回值等。
下面,我们先来熟悉一下SOAP协议,看看它是如何描述程序中的函数方法、参数及结果对象的。
SOAP协议简介
什么是SOAP
SOAP 指简单对象访问协议,它是一种基于XML的消息通讯格式,用于网络上,不同平台,不同语言的应用程序间的通讯。可自定义,易于扩展。一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素:
• Envelope 元素,标识XML 文档一条 SOAP 消息
• Header 元素,包含头部信息的XML标签
• Body 元素,包含所有的调用和响应的主体信息的标签
• Fault 元素,错误信息标签。
以上的元素都在 SOAP的命名空间http://www.w3.org/2001/12/soap-envelope中声明;
SOAP的语法规则
• SOAP 消息必须用 XML 来编码
• SOAP 消息必须使用 SOAP Envelope 命名空间
• SOAP 消息必须使用 SOAP Encoding 命名空间
• SOAP 消息不能包含 DTD 引用
• SOAP 消息不能包含 XML 处理指令
SOAP 消息的基本结构
Java代码
1. <? xml version="1.0"?>
2. <soap:Envelope
3. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
4. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
5. <soap:Header>
6. ...
7. ...
8. </soap:Header>
9. <soap:Body>
10. ...
11. ...
12. <soap:Fault>
13. ...
14. ...
15. </soap:Fault>
16. </soap:Body>
17. </soap:Envelope>
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
...
...
</soap:Header>
<soap:Body>
...
...
<soap:Fault>
...
...
</soap:Fault>
</soap:Body>
</soap:Envelope>
SOAP Envelope 元素
Envelope 元素是 SOAP 消息的根元素。它指明 XML 文档是一个SOAP 消息。它的属性 xmlns:soap的值必须是http://www.w3.org/2001/12/soap-envelope。
encodingStyleu 属性,语法:soap:encodingStyle="URI"
encodingStyle 属性用于定义文档中使用的数据类型。此属性可出现在任何 SOAP 元素中,并会被应用到元素的内容及元素的所有子元素上。
Java代码
1. <? xml version="1.0"?>
2. <soap:Envelope
3. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
4. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
5. ...
6. Message information goes here
7. ...
8. </soap:Envelope>
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
...
Message information goes here
...
</soap:Envelope>
SOAP Header 元素
· actor 属性,语法soap:actor="URI"
通过沿着消息路径经过不同的端点,SOAP 消息可从某个发送者传播到某个接收者。并非 SOAP 消息的所有部分均打算传送到 SOAP 消息的最终端点,不过,另一个方面,也许打算传送给消息路径上的一个或多个端点。SOAP 的 actor 属性可被用于将 Header 元素寻址到一个特定的端点。
· mustUnderstand 属性 ,语法soap:mustUnderstand="0|1"
SOAP 的 mustUnderstand 属性可用于标识标题项对于要对其进行处理的接收者来说是强制的还是可选的。假如您向 Header 元素的某个子元素添加了 "mustUnderstand="1",则要求处理此头部的接收者必须认可此元素。
Java代码
1. <? xml version="1.0"?>
2. <soap:Envelope
3. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
4. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
5. <soap:Header>
6. <m:Trans
7. xmlns:m="
8. soap:mustUnderstand="1"
9. soap:actor=" “ >234</m:Trans>
10. </soap:Header>
11. ...
12. ...
13. </soap:Envelope>
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
<m:Trans
xmlns:m="
soap:mustUnderstand="1"
soap:actor=" “ >234</m:Trans>
</soap:Header>
...
...
</soap:Envelope>
SOAP Body 元素
必需的 SOAP Body 元素可包含打算传送到消息最终端点的实际 SOAP 消息。Body元素中既可以包含SOAP定义的命名空间中的元素,如Fault,也可以是用户的应用程序自定义的元素。以下是一个用户定义的请求:
Java代码
1. <? xml version="1.0"?>
2. <soap:Envelope
3. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
4. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
5. <soap:Body>
6. <m:GetPrice xmlns:m="
7. <m:Item>Apples</m:Item>
8. </m:GetPrice>
9. </soap:Body>
10. </soap:Envelope>
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body>
<m:GetPrice xmlns:m="
<m:Item>Apples</m:Item>
</m:GetPrice>
</soap:Body>
</soap:Envelope>
上面的例子请求苹果的价格。请注意,上面的 m:GetPrice 和 Item 元素是应用程序专用的元素。它们并不是 SOAP 标准的一部分。而对应的 SOAP 响应应该类似这样:
Java代码
1. <?xml version="1.0"?>
2. <soap:Envelope
3. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
4. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
5. <soap:Body>
6. <m:GetPriceResponse xmlns:m="
7. <m:Price>1.90</m:Price>
8. </m:GetPriceResponse>
9. </soap:Body>
10. </soap:Envelope>
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body>
<m:GetPriceResponse xmlns:m="
<m:Price>1.90</m:Price>
</m:GetPriceResponse>
</soap:Body>
</soap:Envelope>
SOAP Fault 元素
Fault 元素表示 SOAP的错误消息。它必须是 Body 元素的子元素,且在一条 SOAP 消息中,Fault 元素只能出现一次。Fault 元素拥有下列子元素:
常用的SOAP Fault Codes
HTTP协议中的SOAP 实例
下面的例子中,一个 GetStockPrice 请求被发送到了服务器。此请求有一个 StockName 参数,而在响应中则会返回一个 Price 参数。此功能的命名空间被定义在此地址中: "
· SOAP 请求:(注意HTTP的Head属性)
Java代码
1. POST /InStock HTTP/1.1
2. Host:
3. Content-Type: application/soap+xml; charset=utf-8
4. Content-Length: XXX
5.
6. <? xml version="1.0"?>
7. <soap:Envelope
8. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
9. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
10. <soap:Body xmlns:m="
11. <m:GetStockPrice>
12. <m:StockName>IBM</m:StockName>
13. </m:GetStockPrice>
14. </soap:Body>
15. </soap:Envelope>
POST /InStock HTTP/1.1
Host:
Content-Type: application/soap+xml; charset=utf-8
Content-Length: XXX
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="
<m:GetStockPrice>
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
· SOAP 响应:(注意HTTP的Head属性)
Java代码
1. HTTP/1.1 200 OK
2. Content-Type: application/soap+xml; charset=utf-8
3. Content-Length: XXX
4.
5. <? xml version="1.0"?>
6. <soap:Envelope
7. xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
8. soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
9. <soap:Body xmlns:m="
10. <m:GetStockPriceResponse>
11. <m:Price>34.5</m:Price>
12. </m:GetStockPriceResponse>
13. </soap:Body>
14. </soap:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: XXX
<? xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="
<m:GetStockPriceResponse>
<m:Price>34.5</m:Price>
</m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>
HTTP协议中的SOAP RPC工作流程
WSDL简介
介绍过了SOAP,让我们关注Web Service中另外一个重要的组成WSDL。
WSDL的主要文档元素
WSDL文档可以分为两部分。顶部分由抽象定义组成,而底部分则由具体描述组成。抽象部分以独立于平台和语言的方式定义SOAP消息,它们并不包含任何随机器或语言而变的元素。这就定义了一系列服务,截然不同的应用都可以实现。具体部分,如数据的序列化则归入底部分,因为它包含具体的定义。在上述的文档元素中,<types>、<message>、<portType>属于抽象定义层,<binding>、<service>属于具体定义层。所有的抽象可以是单独存在于别的文件中,也可以从主文档中导入。
WSDL文档的结构实例解析
下面我们将通过一个实际的WSDL文档例子来详细说明各标签的作用及关系。
Java代码
1. <?xml version="1.0" encoding="UTF-8"?>
2. <definitions
3. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
4. xmlns:tns="
5. xmlns:xsd="http://www.w3.org/2001/XMLSchema"
6. xmlns="http://schemas.xmlsoap.org/wsdl/"
7. targetNamespace="
8. name="Example">
9.
10. <types>
11. <xsd:schema>
12. <xsd:import
13. namespace="
14. schemaLocation="http://localhost:8080/hello?xsd=1"></xsd:import>
15. </xsd:schema>
16. </types>
17.
18. <message name="toSayHello">
19. <part name="userName" type="xsd:string"></part>
20. </message>
21. <message name="toSayHelloResponse">
22. <part name="returnWord" type="xsd:string"></part>
23. </message>
24.
25. <message name="sayHello">
26. <part name="person" type="tns:person"></part>
27. <part name="arg1" type="xsd:string"></part>
28. </message>
29. <message name="sayHelloResponse">
30. <part name="personList" type="tns:personArray"></part>
31. </message>
32. <message name="HelloException">
33. <part name="fault" element="tns:HelloException"></part>
34. </message>
35.
36. <portType name="Example">
37. <operation name="toSayHello" parameterOrder="userName">
38. <input message="tns:toSayHello"></input>
39. <output message="tns:toSayHelloResponse"></output>
40. </operation>
41. <operation name="sayHello" parameterOrder="person arg1">
42. <input message="tns:sayHello"></input>
43. <output message="tns:sayHelloResponse"></output>
44. <fault message="tns:HelloException" name="HelloException"></fault>
45. </operation>
46. </portType>
47.
48. <binding name="ExamplePortBinding" type="tns:Example">
49. <soap:binding
50. transport="http://schemas.xmlsoap.org/soap/http"
51. style="rpc"></soap:binding>
52. <operation name="toSayHello">
53. <soap:operation soapAction="sayHello"></soap:operation>
54. <input>
55. <soap:body use="literal"
56. namespace="
57. </input>
58. <output>
59. <soap:body use="literal"
60. namespace="
61. </output>
62. </operation>
63. <operation name="sayHello">
64. <soap:operation soapAction="sayHello"></soap:operation>
65. <input>
66. <soap:body use="literal"
67. namespace="
68. </input>
69. <output>
70. <soap:body use="literal"
71. namespace="
72. </output>
73. <fault name="HelloException">
74. <soap:fault name="HelloException" use="literal"></soap:fault>
75. </fault>
76. </operation>
77. </binding>
78.
79. <service name="Example">
80. <port name="ExamplePort" binding="tns:ExamplePortBinding">
81. <soap:address location="http://localhost:8080/hello"></soap:address>
82. </port>
83. </service>
84. </definitions>
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="
name="Example">
<types>
<xsd:schema>
<xsd:import
namespace="
schemaLocation="http://localhost:8080/hello?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="toSayHello">
<part name="userName" type="xsd:string"></part>
</message>
<message name="toSayHelloResponse">
<part name="returnWord" type="xsd:string"></part>
</message>
<message name="sayHello">
<part name="person" type="tns:person"></part>
<part name="arg1" type="xsd:string"></part>
</message>
<message name="sayHelloResponse">
<part name="personList" type="tns:personArray"></part>
</message>
<message name="HelloException">
<part name="fault" element="tns:HelloException"></part>
</message>
<portType name="Example">
<operation name="toSayHello" parameterOrder="userName">
<input message="tns:toSayHello"></input>
<output message="tns:toSayHelloResponse"></output>
</operation>
<operation name="sayHello" parameterOrder="person arg1">
<input message="tns:sayHello"></input>
<output message="tns:sayHelloResponse"></output>
<fault message="tns:HelloException" name="HelloException"></fault>
</operation>
</portType>
<binding name="ExamplePortBinding" type="tns:Example">
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
style="rpc"></soap:binding>
<operation name="toSayHello">
<soap:operation soapAction="sayHello"></soap:operation>
<input>
<soap:body use="literal"
namespace="
</input>
<output>
<soap:body use="literal"
namespace="
</output>
</operation>
<operation name="sayHello">
<soap:operation soapAction="sayHello"></soap:operation>
<input>
<soap:body use="literal"
namespace="
</input>
<output>
<soap:body use="literal"
namespace="
</output>
<fault name="HelloException">
<soap:fault name="HelloException" use="literal"></soap:fault>
</fault>
</operation>
</binding>
<service name="Example">
<port name="ExamplePort" binding="tns:ExamplePortBinding">
<soap:address location="http://localhost:8080/hello"></soap:address>
</port>
</service>
</definitions>
由于上面的事例XML较长,我们将其逐段分解讲解
WSDL文档的根元素:<definitions>
Java代码
1. <definitions
2. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
3. xmlns:tns="
4. xmlns:xsd="http://www.w3.org/2001/XMLSchema"
5. xmlns="http://schemas.xmlsoap.org/wsdl/"
6. targetNamespace="
7. name="Example">
8. ……
9. ……
10. </definitions>
<definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="
name="Example">
……
……
</definitions>
<definitions>定义了文档中用到的各个xml元素的namespace缩写,也界定了本文档自己的targetNamespace="
展开阅读全文