So easy Webservice 5.WSDL 文件说明

WSDL – WebService Description Language – Web服务描述语言

通过XML形式说明服务在什么地方-地址。

通过XML形式说明服务提供什么样的方法 – 如何调用。

 

<wsdl:service name="MobileCodeWS">
  <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><a href="http://www.webxml.com.cn/" target="_blank">WebXml.com.cn</a> <strong>国内手机号码归属地查询WEB服务</strong>,提供最新的国内手机号码段归属地数据,每月更新。<br />使用本站 WEB 服务请注明或链接本站:<a href="http://www.webxml.com.cn/" target="_blank">http://www.webxml.com.cn/</a> 感谢大家的支持!<br />&nbsp;</wsdl:documentation> 
- <wsdl:port name="MobileCodeWSSoap" binding="tns:MobileCodeWSSoap">
  <soap:address location="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx" /> 
  </wsdl:port>

<wsdl:binding name="MobileCodeWSSoap" type="tns:MobileCodeWSSoap">

 

WSDL语法分析

前面获取web的发布信息是通过wsimport 来解析wsdl文件得到Java类来实现的. 如论是获取发布的服务,还是调用发布的服务.都需要参考wsdl文件.接下面我们就来分析wsdl文件的结构.

 

分析服务类相关信息

// HelloWorldService 就是我们注册的服务,默认在原来的类名后面加上Service
<service name="HelloWorldService">
  // 可以通过getHelloWroldPort()获取基于soap1.1的服务,此服务接受的类型取决,
// HelloWorldServiceSoapBinding绑定的类型
<port name="HelloWorldPort" binding="tns:HelloWorldPortBinding">
// 提供服务的地址,和端口,SOAP后面介绍
  <soap:address location="http://127.0.0.1:9999/helloworld" /> 
  </port>
</service>

分析如何调用服务方法

/ 上面中的HelloWorldPortBinding参照的就是此HelloWorldPortBinding它的类型为HelloWorld接口类型.
<binding name="HelloWorldPortBinding" type="tns:HelloWorld">
  // SOAP1.1协议 http://schemas.xmlsoap.org/soap/http
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> 
      // 此服务拥有操作的方法
<operation name="sayHi">
  <soap:operation soapAction="" /> 
<input>
      <soap:body use="literal" /> 
  </input>
 <output>
      <soap:body use="literal" /> 
  </output>
  </operation>
</binding>

 


 

WSDL详解

 

WSDL 文档的组成部分

元素

定义

<portType>

web service 执行的操作

<message>

web service 使用的消息

<types>

web service 使用的数据类型

<binding>

web service 使用的通信协议

 

WSDL 文档的主要结构:

<definitions>

<types>

   definition of types........

</types>

<message>

   definition of a message....

</message>

<portType>

   definition of a port.......

</portType>

<binding>

   definition of a binding....

</binding>

</definitions>

WSDL元素介绍

定义一个功能,在Java中叫做方法,在C中叫做函数;在Java中叫类,在C语言中叫做结构体。这些名词都不一样。

WSDL规范为了不会产生歧义,就定义了一些新的名词来表述功能与服务。

<portType>WSDL端口

<portType> 元素是最重要的 WSDL 元素。 它可描述一个 web service、可被执行的操作,以及相关的消息。 可以把 <portType> 元素比作传统编程语言中的一个函数库(或一个模块、或一个类)。 

<operation>子元素:

对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。

<message> WSDL消息)

<message> 元素定义一个操作的数据元素。 每个消息均由一个或多个部件组成。可以把这些部件比作传统编程语言中一个函数调用的参数。 

通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。

<types>WSDL types

<types> 元素定义 web service 使用的数据类型。 为了最大程度的平台中立性,WSDL 使用 XML Schema 语法来定义数据类型。 

 

<binding> WSDL Bindings

<binding> 元素为每个端口定义消息格式和协议细节。

示例

这是某个 WSDL 文档的简化的片段: 

<message name="getTermRequest">

   <part name="term" type="xs:string"/>

</message>

 

<message name="getTermResponse">

   <part name="value" type="xs:string"/>

</message>

 

<portType name="glossaryTerms">

  <operation name="getTerm">

        <input message="getTermRequest"/>

        <output message="getTermResponse"/>

  </operation>

</portType>

 

 

在这个例子中,<portType> 元素把 "glossaryTerms" 定义为某个端口的名称,把 "getTerm" 定义为某个操作的名称。

 

操作 "getTerm" 拥有一个名为 "getTermRequest" 的输入消息,以及一个名为 "getTermResponse" 的输出消息。

 

<message> 元素可定义每个消息的部件,以及相关联的数据类型。

 

对比传统的编程,glossaryTerms 是一个函数库,而 "getTerm" 是带有输入参数 "getTermRequest" 和返回参数 getTermResponse 的一个函数。

 

说明

TypesMessagePortTypeOpration为抽象定义。

BindingPortService是实现。

 

Port:

定义为协议/数据格式绑定与具体web访问地址组合的单个服务访问点。

 

Service:

相关服务访问点的集合。

 

 

问题思考:

通过上面的学习我们已经知道如何通过阅读WSDL文档来调用Web服务.但是到目前为止我们还不能通过AJAX的方式来调用我们自己发布的服务.因为我们并不知道我们自己发布服务的SOAP信息,可以使用MyEclipse提供的工具WebServiceExplorer

 

WebServiceExplorer使用

 

WebServiceExplorer使用步骤

  1. 首先打开web service Explore浏览器à单击右边的WSDL PAGEà在Open WSDL中输入网址http://127.0.0.1:9999/helloworld?wsdl  然后单击go既可
  2. 在图的左边会罗列出已经注册的web服务类和服务方法(注意JDK1.6不支持SOAP1.2协议.所以在网上发布了wsdl服务如果是基于1.2的则得不到任何有效信息),测试任何一个方法可以得到类似如下格式的代码:

 

SOAP Request Envelope:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://myws.ws.e.oocl.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<soapenv:Body>

<q0:sayHi>

        <arg0>china</arg0> 

      </q0:sayHi>

  </soapenv:Body>

</soapenv:Envelope>

 

SOAP Response Envelope:    

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">

<S:Body>

     <ns2:sayHiResponse xmlns:ns2="http://myws.ws.e.oocl.cn/">

     <return>hello---->china</return> 

   </ns2:sayHiResponse>

  </S:Body>

</S:Envelope>

 

我们通过WebServiceExplorer工具会发现.基于Java代码的WS服务的调用本质上还是发送了HTTP1.1协议+传输的数据不但有数据本身而且还有对数据的描述. HTTP 请求体传输的是一种特殊的XML,它就是SOAP

 

SOAP协议简单介绍

名词3:SOAP-Simple Object Access Protocol(简单对象访问协议)

1 SOAP作为一个基于XML语言的协议用于有网上传输数据。

2 SOAP = 在HTTP的基础上+XML数据。

3 SOAP的组成

Envelope – 必须的部分。以XML的根元素出现。

Headers – 可选的。

Body – 必须的。在body部分包含要执行的服务器的方法。和发送到服务器数据。

Soap:是HTTP POST的一个专用版本,遵循一种特殊的xml消息格式Content-type设置为: text/xml任何数据都可以xml化。

 

采用AJAX  调用自己发布的WebService

<body>

        <button onclick="mobile()">test</button>

</body>

<script language="javascript">

// 1:创建XMLHTTP对象

var xhr=null;

function mobile(){

// 声明在访问的ws的地址

var url="http://127.0.0.1:9999/helloworld"

// 书写要发送的XML文件,即 SOAP

var soap='<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ' + 

'xmlns:q0="http://myws.ws.e.oocl.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +

'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +

'<soapenv:Body>' +

'<q0:sayHi>' +

'<arg0>china</arg0>' + 

'</q0:sayHi>' +

'</soapenv:Body>' +

'</soapenv:Envelope>'

// 3:打开连接

xhr.open("post",url,true);

xhr.onreadystatechange=callBack;

xhr.setRequestHeader("Content-Type","text/xml; charset=utf-8");

xhr.send(soap);

}

function callBack(){

if(xhr.readyState==4){

var a=xhr.responseXML;

alert(xhr.responseXML.getElementsByTagName("return")[0].text);

}

}

function init(){

xhr=new ActiveXObject("MSXML2.XMLHTTP.3.0");

}

init();

</script>

 

ServiceExplorer阶段总结:

通过上面的AJAX调用我们会发现的确可以实现相同的功能但是细心的同学们会发现我们自己生成的SOAP和官方提供的SOAP不同那么我们如何来修改标签和命名空间的潜前缀呢这就要我们下面学到的注解了

使用WebService注解来修改WSDL文件

 

WSDL文件的内容,一般由服务默认生成,但为了更好的向开发人员提供使用说明书,一般应做一些简单的修改。至少不应该暴露我们的包结构。targetNamespace默认情况下为倒置的包名,这已经暴露了我们的包结构。通过在类文件上添加以下注解,可以修改wsdl生成的各元素,而不是直接去修改wsdl文件,直接去修改wsdl文件是无效的。

WebService的注解包括:

  1. @WebService-定义服务   --类上
  2. @WebMethod-定义方法   - 方法
  3. @WebResult-定义返回值 – 返回值 
  4. @WebParam-定义参数 – 参数

 

WebService注解的使用

  1. 通过WebService的注解,可以更加形像的描述Web服务。从而生成WSDL文档。
  2. 当修改了WebService注解之后,同时会影响客户端生成的代码。
  3. 调用的方法名和参数名也发生了变化。
  4. 即使是没有修改源代码,只修改了注解,客户端的代码也必须要重新生成(注意是生成而不是下载)。否则调用将会失败。
  5. 生成本地调用代码,依然使用wsimport工具

 

@WebService注解:

  1. @WebService 标注要暴露为Web Services的类或接口 ,用于修饰类或接口,包含的属性有:
  2. targetNamespace属性:定义命名空间,默认为”http://”+”包名倒排
  3. name属性:Web Service 的名称,默认为发布服务的类名。 
  4. serviceName: ws服务的名词,默认在类名后面添加了service 
  5. endpointInterface属性:定义服务抽象 Web Service 协定的服务端点接口的完整名称,接口也必须声明WebService注解,包括方法的注解必须也要添加到接口中,否则会无效而且WS在没有注解的情况下.生成WS的时候会自动生成一个注解.所以可以不用指定接口

 

@WebMethod

  1. 此注解用在方法上,用于修改对外暴露的方法
  2. operationName属性:与此方法匹配的 wsdl:operation 的名称
  3. exclude属性:标注此方法是否被暴露,默认为false

 

注意:如果所有方法上都没有指定@WebMethod,则默认是所有的方法都是对外暴露的方法。如果有任一方法指定了@WebMethod,则只有指定这个注解的才是对外暴露的方法。

 

@WebResult

@WebResult 定义返回值,返回值类型不能为接口类或抽象类,而且必须有个不带参的构造函数,包含属性

name属性:返回值的名称

 

一个添加注解的案例:

// 修改web服务的名称,和命名空间

@WebService(name="Hello",targetNamespace="http://icast.cn")

public class HelloWorld {

@WebMethod(operationName="aaa")

// 修改webResult 和 webParam会影响到JS的调用模式

public @WebResult(name="returnName") String sayHi(@WebParam(name="yourname") String name){

return "Hello" + name;

}

 

public static void main(String[] args){

// 发布一个web服务,指定IP和实现者

Endpoint end=Endpoint.publish("http://127.0.0.1:4567/hello",new HelloWorld());

}

}

posted @ 2016-01-27 16:59  艺言弈行  阅读(736)  评论(0编辑  收藏  举报