`
阅读更多

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>  



SOAP Envelope 元素
Envelope 元素是 SOAP 消息的根元素。它指明 XML 文档是一个SOAP 消息。它的属性 xmlns:soap的值必须是http://www.w3.org/2001/12/soap-envelope。
 encodingStyle 属性,语法: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>  



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= "http://www.jsoso.net/transaction/"     
  8. soap:mustUnderstand= "1"     
  9. soap:actor="http: //www.w3schools.com/appml/ “  >234</m:Trans>   
  10. </soap:Header>   
  11. ...   
  12. ...   
  13. </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= "http://www.jsoso.net/prices" >   
  7.       <m:Item>Apples</m:Item>   
  8.    </m:GetPrice>   
  9. </soap:Body>   
  10. </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= "http://www.jsoso.net/prices" >   
  7.       <m:Price> 1.90 </m:Price>   
  8.    </m:GetPriceResponse>   
  9. </soap:Body>   
  10. </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属性)

 

Java代码
  1. POST /InStock HTTP/ 1.1   
  2. Host: www.jsoso.net   
  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= "http://www.jsoso.net/stock" >   
  11.     <m:GetStockPrice>   
  12.       <m:StockName>IBM</m:StockName>   
  13.     </m:GetStockPrice>   
  14.   </soap:Body>     
  15. </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= "http://www.jsoso.net/stock" >   
  10.     <m:GetStockPriceResponse>   
  11.       <m:Price> 34.5 </m:Price>   
  12.     </m:GetStockPriceResponse>   
  13.   </soap:Body>     
  14. </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= "http://www.jsoso.com/wstest"   
  5.  xmlns:xsd= "http://www.w3.org/2001/XMLSchema"   
  6.  xmlns= "http://schemas.xmlsoap.org/wsdl/"   
  7.  targetNamespace= "http://www.jsoso.com/wstest"   
  8.  name= "Example" >   
  9.   
  10. <types>   
  11.   <xsd:schema>   
  12.   <xsd: import   
  13.    namespace= "http://www.jsoso.com/wstest"   
  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= "http://www.jsoso.com/wstest" ></soap:body>   
  57.     </input>   
  58.     <output>   
  59.       <soap:body use= "literal"   
  60.          namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  61.     </output>   
  62.   </operation>   
  63.   <operation name= "sayHello" >   
  64.     <soap:operation soapAction= "sayHello" ></soap:operation>   
  65.     <input>   
  66.       <soap:body use= "literal"   
  67.         namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  68.     </input>   
  69.     <output>   
  70.       <soap:body use= "literal"   
  71.         namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  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较长,我们将其逐段分解讲解

WSDL文档的根元素:<definitions>

Java代码
  1. <definitions   
  2.  xmlns:soap= "http://schemas.xmlsoap.org/wsdl/soap/"   
  3.  xmlns:tns= "http://www.jsoso.com/wstest"   
  4.  xmlns:xsd= "http://www.w3.org/2001/XMLSchema"   
  5.  xmlns= "http://schemas.xmlsoap.org/wsdl/"   
  6.  targetNamespace= "http://www.jsoso.com/wstest"   
  7.  name= "Example" >   
  8. ……   
  9. ……   
  10. </definitions>  


<definitions>定义了文档中用到的各个xml元素的namespace缩写,也界定了本文档自己的 targetNamespace="http://www.jsoso.com/wstest",这意味着其它的XML要引用当前XML中的元素时,要声 明这个namespace。注意xmlns:tns="http://www.jsoso.com/wstest"这个声明,它标示了使用tns这个前缀 指向自身的命名空间。

引用
WSDL文档数据类型定义元素:<types>

 

Java代码
  1. <types>   
  2.   <xsd:schema>   
  3.   <xsd: import   
  4.    namespace= "http://www.jsoso.com/wstest"   
  5.    schemaLocation= "http://localhost:8080/hello?xsd=1" ></xsd: import >   
  6.   </xsd:schema>   
  7. </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 >

Java代码
  1. <message name= "toSayHello" >   
  2.   <part name= "userName"  type= "xsd:string" ></part>   
  3. </message>   
  4. <message name= "toSayHelloResponse" >   
  5.   <part name= "returnWord"  type= "xsd:string" ></part>   
  6. </message>   
  7.   
  8. <message name= "sayHello" >   
  9.   <part name= "person"  type= "tns:person" ></part>   
  10.   <part name= "arg1"  type= "xsd:string" ></part>   
  11. </message>   
  12. <message name= "sayHelloResponse" >   
  13.   <part name= "personList"  type= "tns:personArray" ></part>   
  14. </message>   
  15. <message name= "HelloException" >   
  16.   <part name= "fault"  element= "tns:HelloException" ></part>   
  17. </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 >

Java代码
  1. <portType name= "Example" >   
  2.   <operation name= "toSayHello"  parameterOrder= "userName" >   
  3.     <input message= "tns:toSayHello" ></input>   
  4.     <output message= "tns:toSayHelloResponse" ></output>   
  5.   </operation>   
  6.   <operation name= "sayHello"  parameterOrder= "person arg1" >   
  7.     <input message= "tns:sayHello" ></input>   
  8.     <output message= "tns:sayHelloResponse" ></output>   
  9.     <fault message= "tns:HelloException"  name= "HelloException" ></fault>   
  10.   </operation>   
  11. </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 >

Java代码
  1. <binding name= "ExamplePortBinding"  type= "tns:Example" >   
  2.   <soap:binding   
  3.     transport= "http://schemas.xmlsoap.org/soap/http"     
  4.     style= "rpc" ></soap:binding>   
  5.   <operation name= "toSayHello" >   
  6.     <soap:operation soapAction= "sayHello" ></soap:operation>   
  7.     <input>   
  8.       <soap:body use= "literal"   
  9.         namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  10.     </input>   
  11.     <output>   
  12.       <soap:body use= "literal"   
  13.          namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  14.     </output>   
  15.   </operation>   
  16.   <operation name= "sayHello" >   
  17.     <soap:operation soapAction= "sayHello" ></soap:operation>   
  18.     <input>   
  19.       <soap:body use= "literal"   
  20.         namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  21.     </input>   
  22.     <output>   
  23.       <soap:body use= "literal"   
  24.         namespace= "http://www.jsoso.com/wstest" ></soap:body>   
  25.     </output>   
  26.     <fault name= "HelloException" >   
  27.       <soap:fault name= "HelloException"  use= "literal" ></soap:fault>   
  28.     </fault>   
  29.     </operation>   
  30. </binding>  


<binding>标签是完整描述协议、序列化和编码的地方,<types>,<message>和<portType>标签处理抽象的数据内容,而<binding>标签是处理数据传输的物理实现。
<binding>标签把前三部分的抽象定义具体化。

首 先<binding>标签使用<soap:binding>的transport和style属性定义了Web Service的通讯协议HTTP和SOAP的请求风格RPC。其次<operation>子标签将portType中定义的 operation同SOAP的请求绑定,定义了操作名称soapAction,输出输入参数和异常的编码方式及命名空间。

WSDL服务地址绑定元素:< service >

Java代码
  1. <service name= "Example" >   
  2.   <port name= "ExamplePort"  binding= "tns:ExamplePortBinding" >   
  3.     <soap:address location= "http://localhost:8080/hello" ></soap:address>   
  4.   </port>   
  5. </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类代码

Java代码
  1. package  org.jsoso.jws.server;   
  2.   
  3. import  java.util.ArrayList;   
  4. import  javax.jws.WebMethod;   
  5. import  javax.jws.WebParam;   
  6. import  javax.jws.WebResult;   
  7. import  javax.jws.WebService;   
  8. import  javax.jws.WebParam.Mode;   
  9. import  javax.jws.soap.SOAPBinding;   
  10. /   
  11.  * 提供WebService服务的类   
  12.  */   
  13. @WebService (name= "Example" , targetNamespace= "http://www.jsoso.com/wstest" , serviceName= "Example" )   
  14. @SOAPBinding (style=SOAPBinding.Style.RPC)   
  15. public   class  Example {   
  16.      private  ArrayList<Person> persons =  new  ArrayList<Person>();;   
  17.      /**  
  18.      *   
  19.      * 返回一个字符串  
  20.      * @param userName  
  21.      * @return  
  22.      */   
  23.      @WebMethod (operationName= "toSayHello" ,action= "sayHello" ,exclude= false )   
  24.      @WebResult (name= "returnWord" ) //自定义该方法返回值在WSDL中相关的描述   
  25.      public  String sayHello( @WebParam (name= "userName" )String userName) {   
  26.          return   "Hello:"  + userName;   
  27.     }   
  28.   
  29.      /**  
  30.      * web services 方法的返回值与参数的类型不能为接口  
  31.      * @param person  
  32.      * @return  
  33.      * @throws HelloException  
  34.      */   
  35.      @WebMethod (operationName= "sayHello" , action= "sayHello" )   
  36.      @WebResult (partName= "personList" )   
  37.      public  Person[] sayHello( @WebParam (partName= "person" , mode=Mode.IN)Person person,    
  38.             String userName)  throws  HelloException {   
  39.          if  (person ==  null  || person.getName() ==  null ) {   
  40.              throw   new  HelloException( "说hello出错,对像为空。。" );   
  41.         }   
  42.         System.out.println(person.getName() +  " 对 "  + userName +  " 说:Hello,我今年"  + person.getAge() +  "岁" );   
  43.         persons.add(person);   
  44.          return  persons.toArray( new  Person[ 0 ]);   
  45.     }   
  46. }  



Annotation 1@WebService(name="Example", targetNamespace="http://www.jsoso.com/wstest", serviceName="Example")
@WebService标签主要将类暴露为WebService,其中targetNamespace属性定义了自己的命名空间,serviceName则定义了< definitions >标签和<service>标签的name属性。

Annotation 2:@SOAPBinding(style=SOAPBinding.Style.RPC)
@SOAPBinding标签定义了WSDL文档中SOAP的消息协议,其中style属性对应SOAP的文档类型,可选的有RPC和DOCUMENT

Annotation 3:@WebMethod(operationName="toSayHello",action="sayHello",exclude=false)
@WebMethod定义Web Service运作的方法,
属性action 对应操作的活动 ,如<soap:operation soapAction="sayHello" />
属性operationName匹配的wsdl:operation 的名称,如<operation name="toSayHello" parameterOrder="userName">
属性exclude 用于阻止将某一继承方法公开为web服务,默认为false

Annotation 4:@WebResult(name="returnWord")
@ WebResult定义方法返回值得名称,如<part name="returnWord" type="xsd:string" />

Annotation 5:@WebParam(partName="person", mode=Mode.IN
@WebParam定义方法的参数名称,如<part name="person" type="tns:person" />,其中mode属性表示参数的流向,可选值有IN / OUT / INOUT

这 里要着重说明的是,上述Web Service类的sayHello方法中,带有HelloException这个异常声明,造成该服务类不能直接发布成Web Service。需要使用wsgen工具为其生存异常Bean。关于wsgen工具的使用,请参考wsgen与wsimport命令说明

发布一个的Java Web Service
在 完成了上述的Web Service Annotation注释后,我们使用wsgen工具为其进行服务资源文件的构造(这里主要是生成一个名为 org.jsoso.jws.server.jaxws.HelloExceptionBean的异常bean类),最后使用以下的类发布Web 服务:

Java代码
  1. package  org.jsoso.jws.server;   
  2.   
  3. import  java.util.LinkedList;   
  4. import  java.util.List;   
  5. import  javax.xml.ws.Binding;   
  6. import  javax.xml.ws.Endpoint;   
  7. import  javax.xml.ws.handler.Handler;   
  8.   
  9. /**  
  10.  * @author zsy 启动web services服务  
  11.  */   
  12. public   class  StartServer {   
  13.   
  14.      /**  
  15.      * @param args  
  16.      */   
  17.      public   static   void  main(String[] args) {   
  18.          /*  
  19.          * 生成Example 服务实例  
  20.          */   
  21.         Example serverBean =  new  Example();   
  22.          /*  
  23.          * 发布Web Service到http://localhost:8080/hello地址  
  24.          */   
  25.         Endpoint endpoint =    
  26.            Endpoint.publish( "http://localhost:8080/hello" , serverBean);   
  27.         Binding binding = endpoint.getBinding();   
  28.          /*  
  29.          * 设置一个SOAP协议处理栈  
  30.          * 这里就简单得打印SOAP的消息文本  
  31.          */   
  32.         List<Handler> handlerChain =  new  LinkedList<Handler>();   
  33.         handlerChain.add( new  TraceHandler());   
  34.         binding.setHandlerChain(handlerChain);   
  35.         System.out.println( "服务已启动 http://localhost:8080/hello" );   
  36.     }   
  37. }  


在控制台运行这个类,就可以使用URL :http://localhost:8080/hello?wsdl 浏览到上文所描述的WSDL的全文了。这说明您的第一个Web Service应用发布成功!

构建Web Service客户端
使用JavaSE6.0构建Web Service的客户端是一件相当简单的事。这里我们要使用到JDK中的另一个命令行工具wsimport。在控制台下输入以下命令:

引用
wsimport -d ./bin -s ./src -p org.jsoso.jws.client.ref http://localhost:8080/hello?wsdl


即可在包org.jsoso.jws.client.ref中生成客户端的存根及框架文件。其中我们要使用的类只有两个:服务类Example_Service和本地接口Example。编写如下客户端,即可调用Web Service服务:

Java代码
  1. package  org.jsoso.jws.client;   
  2.   
  3. import  org.jsoso.jws.client.ref.*;   
  4.   
  5. public   class  RunClient {   
  6.   
  7.      /**  
  8.      * @param args  
  9.      */   
  10.      public   static   void  main(String[] args) {   
  11.          //初始化服务框架类   
  12.         Example_Service service =  new  Example_Service();   
  13.          //或者本地服务借口的实例   
  14.         Example server = (Example) service.getExamplePort();   
  15.          try  {   
  16.              //调用web service的toSayHello方法   
  17.             System.out.println( "输入toSayHello的返回值——"  + server.toSayHello( "阿土" ));            
  18.              Person person =  new  Person();   
  19.              person.setName( "阿土" );   
  20.              person.setAge( 25 );   
  21.               //调用web service的sayHello方法   
  22.              server.sayHello(person,  "机器人" );   
  23.                 
  24.              person =  new  Person();   
  25.              person.setName( "aten" );   
  26.              person.setAge( 30 );   
  27.               //调用web service的sayHello方法   
  28.              PersonArray list = server.sayHello(person,  "机器人" );   
  29.              //输出返回值   
  30.              System.out.println( "\n以下输入sayHello的返回值——" );   
  31.              for  (Person p : list.getItem()) {   
  32.                 System.out.println(p.getName() +  ":"  + p.getAge());   
  33.             }              
  34.         }  catch  (HelloException_Exception e) {   
  35.             e.printStackTrace();   
  36.         }   
  37.     }   
  38. }  


届此,本次Web Service的学习暂告一个段落。Java Web Service是一个相当庞大的知识体系,其中涉及的相关技术较多,这里无法一一道来,我们将会在今后的开发和使用中,同大家做进一步深入的探讨和学习。

附录:wsgen与wsimport命令说明

wsgen
wsgen 是在JDK的bin目录下的一个exe文件(Windows版),该命令的主要功能是用来生成合适的JAX-WS。它读取Web Service的终端类文件,同时生成所有用于发布Web Service所依赖的源代码文件和经过编译过的二进制类文件。这里要特别说明的是,通常在Web Service Bean中用到的异常类会另外生成一个描述Bean,如果Web Service Bean中的方法有申明抛出异常,这一步是必需的,否则服务器无法绑定该对像。此外,wsgen还能辅助生成WSDL和相关的xsd文件。wsgen从资 源文件生成一个完整的操作列表并验证web service是否合法,可以完整发布。
命令参数说明:

  •  -cp 定义classpath
  •  -r 生成 bean的wsdl文件的存放目录
  •  -s 生成发布Web Service的源代码文件的存放目录(如果方法有抛出异常,则会生成该异常的描述类源文件)
  •  -d 生成发布Web Service的编译过的二进制类文件的存放目录(该异常的描述类的class文件)


命令范例: wsgen -cp ./bin -r ./wsdl -s ./src -d ./bin -wsdl org.jsoso.jws.server.Example

wsimport
wsimport 也是在JDK的bin目录下的一个exe文件(Windows版),主要功能是根据服务端发布的wsdl文件生成客户端存根及框架,负责与Web Service 服务器通信,并在将其封装成实例,客户端可以直接使用,就像使用本地实例一样。对Java而言,wsimport帮助程序员生存调用web service所需要的客户端类文件.java和.class。要提醒指出的是,wsimport可以用于非Java的服务器端,如:服务器端也许是C# 编写的web service,通过wsimport则生成Java的客户端实现。
命令参数说明:

  •  -d 生成客户端执行类的class文件的存放目录
  •  -s 生成客户端执行类的源文件的存放目录
  •  -p 定义生成类的包名


命令范例: wsimport -d ./bin -s ./src -p org.jsoso.jws.client.ref http://localhost:8080/hello?wsdl

分享到:
评论

相关推荐

    Web Service概述及应用

    Web Service、CXF框架是解决跨平台和跨语言的通信技术

    嵌入式Web Service

    二、嵌入式Web Service概述 嵌入式Web Service是指运行在嵌入式设备上的Web服务,能够通过网络协议与其他设备或服务器进行交互。与传统Web服务相比,它更侧重于资源受限环境下的高性能、低功耗和实时性,适用于智能...

    典型的Web Service结构

    #### 一、Web Service 概述 Web Service是一种标准的、跨平台的应用程序接口(API),它允许不同技术、不同语言编写的软件通过网络进行交互。无论Web Service是使用何种工具和技术开发的,只要采用SOAP协议并通过HTTP...

    基于Delphi的Web Service 客户端调用

    #### 一、Web Service 概述 ##### 1.1 Web Service 的定义及特点 Web Service 是一种新型的网络应用程序,它具有自包含(Self-Contained)、自描述(Self-Describing)以及模块化的特点。Web Service 通过网络发布...

    web service 教程,pdf 讲义

    #### 一、Web Service 概述与架构 - **定义**:Web Service 是一种跨编程语言和操作系统平台的、允许应用程序之间进行交互的网络服务。 - **目的**:实现不同系统之间的通信,增强系统的互操作性。 - **架构**: - ...

    编写基于.net的WEB SERVICE.rar

    一、Web Service概述 Web Service是通过XML、SOAP(简单对象访问协议)和WSDL(Web服务描述语言)等标准定义的接口,可以被任何支持这些标准的客户端调用。其核心优势在于实现了分布式计算,允许不同的应用系统之间...

    基于Web Service的3G手机应用开发入门讲座

    【Web Service概述】 Web Service是一种基于开放标准的互联网通信协议,允许不同的系统和服务之间进行交互,从而实现跨平台、跨语言的数据交换。它的核心思想是将业务逻辑封装为可供网络调用的服务,使得应用程序...

    CTIOS Web Service

    #### 一、CTIOS Web Service概述 - **定义与功能:**CTIOS Web Service是一种专门为客户提供一系列Web方法的服务平台,这些方法主要用于执行第三方代理状态控制(Third Party Agent State Control)、呼叫控制...

    Web Service 实战

    #### Web Service概述 Web Service是一种遵循特定标准(如XML、SOAP、WSDL等)设计的网络服务,用于实现不同应用程序间的通信。它允许跨平台、跨语言的数据交换和业务逻辑调用,广泛应用于分布式系统集成和微服务...

    WinCE 利用Web Service查询数据库

    #### Web Service概述 Web Service是一种开放式的标准,用于在不同的平台上进行通信和服务交互。它基于XML和HTTP协议,可以跨平台、跨语言地提供服务。在WinCE应用中,Web Service通常用于与远程服务器交互数据或...

    利用Web Service设计IP.doc

    #### Web Service概述 Web Service是一种遵循特定标准(如XML、SOAP、WSDL等)构建的网络服务,它允许不同平台上的应用程序通过HTTP协议进行通信和数据交换。这种服务通常由一组接口定义,这些接口可以被远程调用,...

    SAP应用及ABAP开发最佳实践—基于ABAP Workbench创建并发布Web Service.pdf

    #### Web Service 概述 - **定义**: Web Service 被定义为一个独立的、模块化的、自我描述的应用功能或服务,它能通过标准互联网协议进行描述、使用、定位或调用。 - **技术基础**: Web Service 主要依赖于 XML ...

    基于Axis2的Web Service 快速开发.ppt

    **Web Service概述** Web Service的核心特性包括: 1. **自包含和自描述**:每个Web Service都是独立的,并且可以通过XML格式的元数据进行描述。 2. **开放和基于标准**:Web Service依赖于一系列开放标准,如WSDL...

    基于Ajax的Web+Service架构

    Web Service概述 Web Service主要用于实现不同系统间的互操作性。其核心优势在于能够在不同的技术平台上实现服务的发现、描述、发布、调用等功能,从而达到无缝集成的目的。Web Service的核心技术包括: - **HTTP...

    WEB SERVICE INTERDUCE

    #### 二、Web Service概述 Web Service是一种用于在网络上发布可被其他应用调用的服务的标准方式。它通常使用HTTP协议,并以XML作为数据交换格式。Web Service的核心技术包括SOAP(Simple Object Access Protocol)...

    基于web service 的工作流系统实现研究

    #### 四、Web Service 概述 Web Service 技术的出现为企业业务集成提供了一种新的解决方案。与传统的分布式计算模型相比,Web Service 提供了更加开放和灵活的服务模型,主要特点包括: - **基于标准**:使用XML...

    Web Service接口

    #### 一、Web Service概述 Web Service,即网络服务,是一种通过标准协议(如HTTP、XML、SOAP等)提供的一种服务,可以在不同的操作系统和编程语言之间进行通信。它允许不同应用程序之间进行交互操作,无需考虑它们...

    mobile web service

    #### 四、Mobile Web Service概述 Mobile Web Service是指通过移动设备访问的Web服务,它充分利用了Web 2.0的理念和技术,为用户提供随时随地的在线服务。随着3G乃至4G网络的快速发展,Mobile Web Service已经成为...

Global site tag (gtag.js) - Google Analytics