- 浏览: 136376 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
tangzlboy:
非常详细,简单易懂!
Struts2入门 -
yeafee:
这里应该是原创了。从他处找来....
用Spring快速开发jms应用(JBOSS服务器) -
effort_fan:
借鉴了。谢谢。
jar命令的使用 -
yhanliang:
简直 就 是从 "李刚" 的 <&l ...
Struts2文件的上传和下载 -
kesun_shy:
哈哈哈啊~
把CSDN上的博客文章在这做了个导入
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 消息的基本结构
SOAP Envelope 元素
Envelope 元素是 SOAP 消息的根元素。它指明 XML 文档是一个SOAP 消息。它的属性 xmlns:soap的值必须是http://www.w3.org/2001/12/soap-envelope。
encodingStyle 属性,语法:soap:encodingStyle="URI"
encodingStyle 属性用于定义文档中使用的数据类型。此属性可出现在任何 SOAP 元素中,并会被应用到元素的内容及元素的所有子元素上。
SOAP Header 元素
通过沿着消息路径经过不同的端点,SOAP 消息可从某个发送者传播到某个接收者。并非 SOAP 消息的所有部分均打算传送到 SOAP 消息的最终端点,不过,另一个方面,也许打算传送给消息路径上的一个或多个端点。SOAP 的 actor 属性可被用于将 Header 元素寻址到一个特定的端点。
SOAP 的 mustUnderstand 属性可用于标识标题项对于要对其进行处理的接收者来说是强制的还是可选的。假如您向 Header 元素的某个子元素添加了 "mustUnderstand="1",则要求处理此头部的接收者必须认可此元素。
SOAP Body 元素
必需的 SOAP Body 元素可包含打算传送到消息最终端点的实际 SOAP 消息。Body元素中既可以包含SOAP定义的命名空间中的元素,如Fault,也可以是用户的应用程序自定义的元素。以下是一个用户定义的请求:
上面的例子请求苹果的价格。请注意,上面的 m:GetPrice 和 Item 元素是应用程序专用的元素。它们并不是 SOAP 标准的一部分。而对应的 SOAP 响应应该类似这样:
SOAP Fault 元素
Fault 元素表示 SOAP的错误消息。它必须是 Body 元素的子元素,且在一条 SOAP 消息中,Fault 元素只能出现一次。Fault 元素拥有下列子元素:
常用的SOAP Fault Codes
HTTP协议中的SOAP 实例
下面的例子中,一个 GetStockPrice 请求被发送到了服务器。此请求有一个 StockName 参数,而在响应中则会返回一个 Price 参数。此功能的命名空间被定义在此地址中: "http://www.jsoso.net/stock"
HTTP协议中的SOAP RPC工作流程
WSDL简介
介绍过了SOAP,让我们关注Web Service中另外一个重要的组成WSDL。
WSDL的主要文档元素
WSDL文档可以分为两部分。顶部分由抽象定义组成,而底部分则由具体描述组成。抽象部分以独立于平台和语言的方式定义SOAP消息,它们并不包含任何随机器或语言而变的元素。这就定义了一系列服务,截然不同的应用都可以实现。具体部分,如数据的序列化则归入底部分,因为它包含具体的定义。在上述的文档元素中,<types>、<message>、<portType>属于抽象定义层,<binding>、<service>属于具体定义层。所有的抽象可以是单独存在于别的文件中,也可以从主文档中导入。
WSDL文档的结构实例解析
下面我们将通过一个实际的WSDL文档例子来详细说明各标签的作用及关系。
由于上面的事例XML较长,我们将其逐段分解讲解
WSDL文档的根元素:<definitions>
<definitions>定义了文档中用到的各个xml元素的namespace缩写,也界定了本文档自己的targetNamespace="http://www.jsoso.com/wstest",这意味着其它的XML要引用当前XML中的元素时,要声明这个namespace。注意xmlns:tns="http://www.jsoso.com/wstest"这个声明,它标示了使用tns这个前缀指向自身的命名空间。
<types>标签定义了当前的WSDL文档用到的数据类型。要说明的是,为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。这些数据类型用来定义web service方法的参数和返回指。对于通用的原生数据类型如:integer , boolean , char , float等,在W3C的标准文档http://www.w3.org/2001/XMLSchema中已经做了定义。这里我们要引入的schema定义schemaLocation="http://localhost:8080/hello?xsd=1"是我们自定义的Java对象类型。
WSDL文档消息体定义元素:< message >
<message>元素定义了web service函数的参数。<message>元素中的每个<part>子元素都和某个参数相符。输入参数在<message>元素中定义,与输出参数相隔离,输出参数有自己的<message>元素。兼作输入、输出的参数在输入输出的<message>元素中有它们相应的<part>元素。输出<message>元素以"Response"结尾,对Java而言方法得返回值就对应一个输出的<message>。每个<part>元素都有名字和类型属性,就像函数的参数有参数名和参数类型。
在上面的文档中有两个输入参数、两个输出参数和一个错误参数(对应Java中的Exception)。
输入参数<message>的name属性分别命名为toSayHello,sayHello。
toSayHello对应输入参数userName,参数类型为xsd:string,在Java语言中就是String;
sayHello对应两个输入参数person和arg1,类型为tns:person和xsd:string。这里tns:person类型就是引用了< types >标签中的类型定义。
输出参数<message>的name属性分别命名为toSayHelloResponse和sayHelloResponse。
这个名称和输入参数的<message>标签name属性对应,在其后面加上Response尾缀。
toSayHelloResponse对应的返回值是returnWord,参数类型为xsd:string;
sayHelloResponse对应的返回值是personList,参数类型为tns:personArray(自定义类型);
错误参数<message>的name属性为HelloException。
它的<part>子标签element而不是type来定义类型。
以上的message标签的name属性通常使用web service函数方法名作为参照,错误参数标签则使用异常类名为参照。标签中的参数名称,即part子元素的name属性是可自定义的(下一章节详细说明)。message标签的参数类型将引用types标签的定义。
WSDL文档函数体定义元素:< portType >
<portType> 元素是最重要的 WSDL 元素。它可描述一个 web service、可被执行的操作,以及相关的消息。portType的name属性对应Java中的一个服务类的类名。<portType> 元素使用其子元素< operation>描述一个web service的服务方法。
在<operation>元素中,name属性表示服务方法名,parameterOrder属性表示方法的参数顺序,使用空格符分割多个参数,如:“parameterOrder="person arg1”。<operation>元素的子标签<input>表示输入参数说明,它引用<message>标签中的输入参数。<output>表示输出参数说明,它引用<message>标签中的输出参数。<fault>标签在Java方法中的特别用来表示异常(其它语言有对应的错误处理机制),它引用<message>标签中的错误参数。
WSDL绑定实现定义元素:< binding >
<binding>标签是完整描述协议、序列化和编码的地方,<types>,<message>和<portType>标签处理抽象的数据内容,而<binding>标签是处理数据传输的物理实现。
<binding>标签把前三部分的抽象定义具体化。
首先<binding>标签使用<soap:binding>的transport和style属性定义了Web Service的通讯协议HTTP和SOAP的请求风格RPC。其次<operation>子标签将portType中定义的operation同SOAP的请求绑定,定义了操作名称soapAction,输出输入参数和异常的编码方式及命名空间。
WSDL服务地址绑定元素:< service >
service是一套<port>元素。在一一对应形式下,每个<port>元素都和一个location关联。如果同一个<binding>有多个<port>元素与之关联,可以使用额外的URL地址作为替换。
一个WSDL文档中可以有多个<service>元素,而且多个<service>元素十分有用,其中之一就是可以根据目标URL来组织端口。在一个WSDL文档中,<service>的name属性用来区分不同的service。在同一个service中,不同端口,使用端口的"name"属性区分。
这一章节,我们简单的描述了WSDL对SOAP协议的支持,以及在Web Service中的作用。在接下来的章节中,我们将学习如何使用Java6.0的Annotation标签来定义和生成对应的WSDL。
JavaSE6.0下的Web Service
从JavaSE6.0开始,Java引入了对Web Service的原生支持。我们只需要简单的使用Java的Annotation标签即可将标准的Java方法发布成Web Service。(PS:Java Annotation资料请参考 JDK5.0 Annotation学习笔记(一) )
但不是所有的Java类都可以发布成Web Service。Java类若要成为一个实现了Web Service的bean,它需要遵循下边这些原则:
下面我们将通过一个具体的Java Web Service代码例子,配合上述的WSDL文件,讲述如何编写JavaSE6.0的原生Web Service应用。
完整的Java 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 消息的基本结构
- <? 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>
<? 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。
encodingStyle 属性,语法:soap:encodingStyle="URI"
encodingStyle 属性用于定义文档中使用的数据类型。此属性可出现在任何 SOAP 元素中,并会被应用到元素的内容及元素的所有子元素上。
- <? 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>
<? 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",则要求处理此头部的接收者必须认可此元素。
- <? 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="http://www.jsoso.net/transaction/"
- soap:mustUnderstand="1"
- soap:actor="http://www.w3schools.com/appml/ “ >234</m:Trans>
- </soap:Header>
- ...
- ...
- </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="http://www.jsoso.net/transaction/" soap:mustUnderstand="1" soap:actor="http://www.w3schools.com/appml/ “ >234</m:Trans> </soap:Header> ... ... </soap:Envelope>
SOAP Body 元素
必需的 SOAP Body 元素可包含打算传送到消息最终端点的实际 SOAP 消息。Body元素中既可以包含SOAP定义的命名空间中的元素,如Fault,也可以是用户的应用程序自定义的元素。以下是一个用户定义的请求:
- <? 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="http://www.jsoso.net/prices">
- <m:Item>Apples</m:Item>
- </m:GetPrice>
- </soap:Body>
- </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="http://www.jsoso.net/prices"> <m:Item>Apples</m:Item> </m:GetPrice> </soap:Body> </soap:Envelope>
上面的例子请求苹果的价格。请注意,上面的 m:GetPrice 和 Item 元素是应用程序专用的元素。它们并不是 SOAP 标准的一部分。而对应的 SOAP 响应应该类似这样:
- <?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="http://www.jsoso.net/prices">
- <m:Price>1.90</m:Price>
- </m:GetPriceResponse>
- </soap:Body>
- </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="http://www.jsoso.net/prices"> <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 参数。此功能的命名空间被定义在此地址中: "http://www.jsoso.net/stock"
- SOAP 请求:(注意HTTP的Head属性)
- POST /InStock HTTP/1.1
- Host: www.jsoso.net
- 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="http://www.jsoso.net/stock">
- <m:GetStockPrice>
- <m:StockName>IBM</m:StockName>
- </m:GetStockPrice>
- </soap:Body>
- </soap:Envelope>
POST /InStock HTTP/1.1 Host: www.jsoso.net 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="http://www.jsoso.net/stock"> <m:GetStockPrice> <m:StockName>IBM</m:StockName> </m:GetStockPrice> </soap:Body> </soap:Envelope>
- SOAP 响应:(注意HTTP的Head属性)
- 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="http://www.jsoso.net/stock">
- <m:GetStockPriceResponse>
- <m:Price>34.5</m:Price>
- </m:GetStockPriceResponse>
- </soap:Body>
- </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="http://www.jsoso.net/stock"> <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文档例子来详细说明各标签的作用及关系。
- <?xml version="1.0" encoding="UTF-8"?>
- <definitions
- xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
- xmlns:tns="http://www.jsoso.com/wstest"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns="http://schemas.xmlsoap.org/wsdl/"
- targetNamespace="http://www.jsoso.com/wstest"
- name="Example">
- <types>
- <xsd:schema>
- <xsd:import
- namespace="http://www.jsoso.com/wstest"
- 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="http://www.jsoso.com/wstest"></soap:body>
- </input>
- <output>
- <soap:body use="literal"
- namespace="http://www.jsoso.com/wstest"></soap:body>
- </output>
- </operation>
- <operation name="sayHello">
- <soap:operation soapAction="sayHello"></soap:operation>
- <input>
- <soap:body use="literal"
- namespace="http://www.jsoso.com/wstest"></soap:body>
- </input>
- <output>
- <soap:body use="literal"
- namespace="http://www.jsoso.com/wstest"></soap:body>
- </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 version="1.0" encoding="UTF-8"?> <definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.jsoso.com/wstest" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.jsoso.com/wstest" name="Example"> <types> <xsd:schema> <xsd:import namespace="http://www.jsoso.com/wstest" 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="http://www.jsoso.com/wstest"></soap:body> </input> <output> <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> </output> </operation> <operation name="sayHello"> <soap:operation soapAction="sayHello"></soap:operation> <input> <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> </input> <output> <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> </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>
- <definitions
- xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
- xmlns:tns="http://www.jsoso.com/wstest"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns="http://schemas.xmlsoap.org/wsdl/"
- targetNamespace="http://www.jsoso.com/wstest"
- name="Example">
- ……
- ……
- </definitions>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.jsoso.com/wstest" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.jsoso.com/wstest" name="Example"> …… …… </definitions>
<definitions>定义了文档中用到的各个xml元素的namespace缩写,也界定了本文档自己的targetNamespace="http://www.jsoso.com/wstest",这意味着其它的XML要引用当前XML中的元素时,要声明这个namespace。注意xmlns:tns="http://www.jsoso.com/wstest"这个声明,它标示了使用tns这个前缀指向自身的命名空间。
引用
WSDL文档数据类型定义元素:<types>
- <types>
- <xsd:schema>
- <xsd:import
- namespace="http://www.jsoso.com/wstest"
- schemaLocation="http://localhost:8080/hello?xsd=1"></xsd:import>
- </xsd:schema>
- </types>
<types> <xsd:schema> <xsd:import namespace="http://www.jsoso.com/wstest" schemaLocation="http://localhost:8080/hello?xsd=1"></xsd:import> </xsd:schema> </types>
<types>标签定义了当前的WSDL文档用到的数据类型。要说明的是,为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。这些数据类型用来定义web service方法的参数和返回指。对于通用的原生数据类型如:integer , boolean , char , float等,在W3C的标准文档http://www.w3.org/2001/XMLSchema中已经做了定义。这里我们要引入的schema定义schemaLocation="http://localhost:8080/hello?xsd=1"是我们自定义的Java对象类型。
WSDL文档消息体定义元素:< message >
- <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>
<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>
<message>元素定义了web service函数的参数。<message>元素中的每个<part>子元素都和某个参数相符。输入参数在<message>元素中定义,与输出参数相隔离,输出参数有自己的<message>元素。兼作输入、输出的参数在输入输出的<message>元素中有它们相应的<part>元素。输出<message>元素以"Response"结尾,对Java而言方法得返回值就对应一个输出的<message>。每个<part>元素都有名字和类型属性,就像函数的参数有参数名和参数类型。
在上面的文档中有两个输入参数、两个输出参数和一个错误参数(对应Java中的Exception)。
输入参数<message>的name属性分别命名为toSayHello,sayHello。
toSayHello对应输入参数userName,参数类型为xsd:string,在Java语言中就是String;
sayHello对应两个输入参数person和arg1,类型为tns:person和xsd:string。这里tns:person类型就是引用了< types >标签中的类型定义。
输出参数<message>的name属性分别命名为toSayHelloResponse和sayHelloResponse。
这个名称和输入参数的<message>标签name属性对应,在其后面加上Response尾缀。
toSayHelloResponse对应的返回值是returnWord,参数类型为xsd:string;
sayHelloResponse对应的返回值是personList,参数类型为tns:personArray(自定义类型);
错误参数<message>的name属性为HelloException。
它的<part>子标签element而不是type来定义类型。
以上的message标签的name属性通常使用web service函数方法名作为参照,错误参数标签则使用异常类名为参照。标签中的参数名称,即part子元素的name属性是可自定义的(下一章节详细说明)。message标签的参数类型将引用types标签的定义。
WSDL文档函数体定义元素:< portType >
- <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>
<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>
<portType> 元素是最重要的 WSDL 元素。它可描述一个 web service、可被执行的操作,以及相关的消息。portType的name属性对应Java中的一个服务类的类名。<portType> 元素使用其子元素< operation>描述一个web service的服务方法。
在<operation>元素中,name属性表示服务方法名,parameterOrder属性表示方法的参数顺序,使用空格符分割多个参数,如:“parameterOrder="person arg1”。<operation>元素的子标签<input>表示输入参数说明,它引用<message>标签中的输入参数。<output>表示输出参数说明,它引用<message>标签中的输出参数。<fault>标签在Java方法中的特别用来表示异常(其它语言有对应的错误处理机制),它引用<message>标签中的错误参数。
WSDL绑定实现定义元素:< binding >
- <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="http://www.jsoso.com/wstest"></soap:body>
- </input>
- <output>
- <soap:body use="literal"
- namespace="http://www.jsoso.com/wstest"></soap:body>
- </output>
- </operation>
- <operation name="sayHello">
- <soap:operation soapAction="sayHello"></soap:operation>
- <input>
- <soap:body use="literal"
- namespace="http://www.jsoso.com/wstest"></soap:body>
- </input>
- <output>
- <soap:body use="literal"
- namespace="http://www.jsoso.com/wstest"></soap:body>
- </output>
- <fault name="HelloException">
- <soap:fault name="HelloException" use="literal"></soap:fault>
- </fault>
- </operation>
- </binding>
<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="http://www.jsoso.com/wstest"></soap:body> </input> <output> <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> </output> </operation> <operation name="sayHello"> <soap:operation soapAction="sayHello"></soap:operation> <input> <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> </input> <output> <soap:body use="literal" namespace="http://www.jsoso.com/wstest"></soap:body> </output> <fault name="HelloException"> <soap:fault name="HelloException" use="literal"></soap:fault> </fault> </operation> </binding>
<binding>标签是完整描述协议、序列化和编码的地方,<types>,<message>和<portType>标签处理抽象的数据内容,而<binding>标签是处理数据传输的物理实现。
<binding>标签把前三部分的抽象定义具体化。
首先<binding>标签使用<soap:binding>的transport和style属性定义了Web Service的通讯协议HTTP和SOAP的请求风格RPC。其次<operation>子标签将portType中定义的operation同SOAP的请求绑定,定义了操作名称soapAction,输出输入参数和异常的编码方式及命名空间。
WSDL服务地址绑定元素:< service >
- <service name="Example">
- <port name="ExamplePort" binding="tns:ExamplePortBinding">
- <soap:address location="http://localhost:8080/hello"></soap:address>
- </port>
- </service>
<service name="Example"> <port name="ExamplePort" binding="tns:ExamplePortBinding"> <soap:address location="http://localhost:8080/hello"></soap:address> </port> </service>
service是一套<port>元素。在一一对应形式下,每个<port>元素都和一个location关联。如果同一个<binding>有多个<port>元素与之关联,可以使用额外的URL地址作为替换。
一个WSDL文档中可以有多个<service>元素,而且多个<service>元素十分有用,其中之一就是可以根据目标URL来组织端口。在一个WSDL文档中,<service>的name属性用来区分不同的service。在同一个service中,不同端口,使用端口的"name"属性区分。
这一章节,我们简单的描述了WSDL对SOAP协议的支持,以及在Web Service中的作用。在接下来的章节中,我们将学习如何使用Java6.0的Annotation标签来定义和生成对应的WSDL。
JavaSE6.0下的Web Service
从JavaSE6.0开始,Java引入了对Web Service的原生支持。我们只需要简单的使用Java的Annotation标签即可将标准的Java方法发布成Web Service。(PS:Java Annotation资料请参考 JDK5.0 Annotation学习笔记(一) )
但不是所有的Java类都可以发布成Web Service。Java类若要成为一个实现了Web Service的bean,它需要遵循下边这些原则:
- 这个类必须是public类
- 这些类不能是final的或者abstract
- 这个类必须有一个公共的默认构造函数
- 这个类绝对不能有finalize()方法
下面我们将通过一个具体的Java Web Service代码例子,配合上述的WSDL文件,讲述如何编写JavaSE6.0的原生Web Service应用。
完整的Java Web Service类代码
- package org.jsoso.jws.server;
- import java.util.ArrayList;
- import javax.jws.WebMethod;
- import javax.jws.WebParam;
- import javax.jws.WebResult;
- import javax.jws.WebService;
- import javax.jws.WebParam.Mode;
- import javax.jws.soap.SOAPBinding;
- /
- * 提供WebService服务的类
- */
- @WebService(name="Example", targetNamespace="http://www.jsoso.com/wstest", serviceName="Example")
- @SOAPBinding(style=SOAPBinding.Style.RPC)
- public class Example {
- private ArrayList<Person> persons = new ArrayList<Person>();;
- /**
- *
- * 返回一个字符串
- * @param userName
- * @return
- */
- @WebMethod(operationName="toSayHello",action="sayHello",exclude=false)
- @WebResult(name="returnWord")//自定义该方法返回值在WSDL中相关的描述
- public String sayHello(@WebParam(name="userName")String userName) {
- return "Hello:" + userName;
- }
- /**
- * web services 方法的返回值与参数的类型不能为接口
- * @param person
- * @return
- * @throws HelloException
- */
- @WebMethod(operationName="sayHello", action="sayHello")
- @WebResult(partName="personList")
- public<sp>
相关推荐
Web Service 即 web 服务,它是一种跨编程语言和跨操作系统平台的远程调用技术。 Java 中共有三种 Web Service 规范: - JAX-WS(JAX-RPC): 基于 xml 数据 - JAXM&SAAJ - JAX-RS:基于 xml 或 json 数据
Web Service是一种基于可编程的Web应用程序,它允许不同系统之间的交互和数据交换,不受平台和编程语言限制。Web Service的核心技术是用于构建Service-Oriented Architecture(SOA)应用。目前,Web Service主要分为...
WebService学习笔记 Web Service 是一种软件系统,为了支持跨网络的机器间相互操作交互而设计。它通常被定义为一组模块化的 API,它们可以通过网络进行调用,来执行远程系统的请求服务。在传统的程序编码中,存在...
里面只有这样几句话:“交易消息(包括请求和应答)是以XML格式表达的,包括两个部分:Message Header(消息头)与Service Content(交易业务内容)。” “接口协议使用HTTP协议,落地方为发起方提供访问的URL,发起方...
本文源自一位开发者陈刚在其个人博客上分享的一篇文章——《[Web Service学习笔记]第1篇 SOAP的HelloWord实例》。该文章发表于2005年,记录了作者在面对一个具体项目需求时,从零开始探索SOAP技术的过程。虽然时间...
**Axis开发Web Service学习笔记** 在信息技术领域,Web服务是一种基于开放标准的互联网通信协议,允许不同的应用程序之间进行互操作。而Axis是Apache软件基金会的一个开源项目,它提供了一个强大的工具集,用于创建...
Web Service入门学习笔记 Web Service是一种基于互联网的、平台无关的通信协议,它允许不同系统间的应用程序通过网络互相调用,实现数据交换和服务共享。在本文中,我们将深入探讨Web Service的基本概念,以及如何...
综上所述,尚硅谷的Web Service学习笔记涵盖了XML Schema、HTTP协议基础以及Web Service的核心概念和应用,为深入理解和实践Web Service提供了基础知识。要了解更多关于Web Service的详细内容,可以通过指定的学习...
【Web Service学习笔记——XFrie框架详解】 Web Service是一种通过网络进行通信的服务,它允许不同的应用程序之间进行数据交换,跨越了操作系统和编程语言的障碍。XFrie是一个轻量级、高性能的Java Web Service框架...
Java/JavaEE 学习笔记 作者在杰普学习时的学习笔记,是J2ee初学者必备手册,是大家学习J2EE开发的很好的参考笔记。 Java/JavaEE 学习笔记 内容目录: Unix 学习笔记..........7 ...Web Service学习笔记.....388
内容目录 .......................1 Java/JavaEE.....1 2008年11月1日...............1 Unix 学习笔记7 一、Unix前言............7 二、Unix基础知识....7 三、Unix常用命令....8 ...Web Service学习笔记.....388
这篇学习笔记将主要围绕JSP展开,探讨其基本概念、语法以及如何在实际开发中运用。 JSP(JavaServer Pages)是一种动态网页技术,它允许开发者在HTML或XML文档中嵌入Java代码,从而实现服务器端的动态内容生成。JSP...
### WebService 学习笔记详解 #### 一、实验环境搭建与配置 在开始Web Service的学习之前,首先需要搭建一个适合开发的环境。本实验基于以下配置: - 操作系统:Windows 2000 (Win2k) - JDK版本:1.6 - Java EE...
在本学习笔记中,主要介绍了使用Apache Axis2框架来开发和测试Web Service的过程。Apache Axis2是Apache SOAP栈的一个实现,提供了简单且高效的Web Service开发工具。 首先,开发者需要在Eclipse集成开发环境中搭建...
- Servlet接收到请求后,调用`service()`方法处理请求。 - 处理完成后,服务器可能会保持Servlet实例以处理后续请求,直到应用程序停止或Servlet被显式卸载。 4. **Servlet生命周期** - 实例化:首次请求Servlet...
以上是关于 JavaWeb 学习笔记中提到的主要知识点,包括 Web 应用的基本概念、目录结构、配置文件详解以及 Tomcat 的虚拟目录和虚拟主机配置方法。希望这些内容能帮助初学者更好地理解 JavaWeb 开发的核心要素和技术...