选自javaee技术体系中的webservice技术
WSDL定义
??? WSDL是一个用于精确描述Web服务的文档,WSDL文档是一个遵循WSDL XML模式的XML文档。WSDL 文档将Web服务定义为服务访问点或端口的集合。在 WSDL 中,由于服务访问点和消息的抽象定义已从具体的服务部署或数据格式绑定中分离出来,因此可以对抽象定义进行再次使用:消息,指对交换数据的抽象描述;而端口类型,指操作的抽象集合。用于特定端口类型的具体协议和数据格式规范构成了可以再次使用的绑定。将Web访问地址与可再次使用的绑定相关联,可以定义一个端口,而端口的集合则定义为服务。
WSDL结构示意图如下:
????? 一个WSDL文档通常包含7个重要的元素,即types、import、message、portType、operation、binding、service元素。这些元素嵌套在definitions元素中,definitions是WSDL文档的根元素。文章的下一部分将会详细介绍WSDL的基本结构。

具体作用说明如下:
-
Types - 数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。
-
Message - 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。
-
Operation - 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对。
-
PortType - 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持。
-
Binding - 特定端口类型的具体协议和数据格式规范的绑定。
-
Port - 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。
-
Service- 相关服务访问点的集合。
WSDL的约束文档schema约束文档链接:http://schemas.xmlsoap.org/wsdl/。
分析
?????? 已笔者写的webservice举例来说明,接口如下:
package com.it.cxf;
import javax.jws.WebService;
@WebService
public interface MyWebService {
public int add(int a,int b);
public int minus(int a,int b);
}
发布后生成的wsdl文件内容如下:
wsdl:definitions name="MyWebServiceImplService" targetNamespace="http://cxf.it.com/">
<wsdl:types>
<xs:schema elementFormDefault="unqualified"
targetNamespace="http://cxf.it.com/" version="1.0">
<xs:element name="add" type="tns:add" />
<xs:element name="addResponse" type="tns:addResponse" />
<xs:element name="minus" type="tns:minus" />
<xs:element name="minusResponse" type="tns:minusResponse" />
<xs:complexType name="add">
<xs:sequence>
<xs:element name="arg0" type="xs:int" />
<xs:element name="arg1" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="addResponse">
<xs:sequence>
<xs:element name="return" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="minus">
<xs:sequence>
<xs:element name="arg0" type="xs:int" />
<xs:element name="arg1" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="minusResponse">
<xs:sequence>
<xs:element name="return" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="minusResponse">
<wsdl:part element="tns:minusResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="addResponse">
<wsdl:part element="tns:addResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="add">
<wsdl:part element="tns:add" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="minus">
<wsdl:part element="tns:minus" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="MyWebService">
<wsdl:operation name="add">
<wsdl:input message="tns:add" name="add">
</wsdl:input>
<wsdl:output message="tns:addResponse" name="addResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="minus">
<wsdl:input message="tns:minus" name="minus">
</wsdl:input>
<wsdl:output message="tns:minusResponse" name="minusResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MyWebServiceImplServiceSoapBinding"
type="tns:MyWebService">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="add">
<soap:operation soapAction="" style="document" />
<wsdl:input name="add">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="addResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="minus">
<soap:operation soapAction="" style="document" />
<wsdl:input name="minus">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="minusResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MyWebServiceImplService">
<wsdl:port binding="tns:MyWebServiceImplServiceSoapBinding"
name="MyWebServiceImplPort">
<soap:address location="http://localhost:8888/ms" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
调用方式一:wsdl2java生成独立客户端代码并调用,
此种方式适用于非服务器端环境下通过暴露的wsdl文件生成独立客户端的情况下:
打开cmd(因为我们配置了环境变量,所以可以直接使用wedl2java命令)
输入
wsdl2java -encoding utf-8 -d D:wswsdl2javatest http://localhost:8080/cxf/server/web-publish?wsdl
生成文件结构如下:

这时,我们变可以写客户端并调用了
package com.it.springmvccxf.impl;
import com.it.springmvccxf.MyWebService;
public class Test {
public static void main(String[] args) {
MyWebServiceImplService implService=new MyWebServiceImplService();
MyWebService service=implService.getMyWebServiceImplPort();
System.out.println(service.add(1,1));
}
}
根据service节点下的name生成实例,在获取端口类型获取端口portType节点,根据该节点下的方法描述进行调用里面的方法。
调用方式二:在服务器开发环境下测试,自己有java服务器,自己调用
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
public class MyClient {
public static void main(String[] args) {
try {
URL url = new URL("http://localhost:8888/ms?wsdl");//wsdl路径
// Qnameqname是qualified name 的简写
//可通过这里获得<wsdl:definitions name="MyWebServiceImplService" targetNamespace="http://cxf.it.com/">
QName qname = new QName("http://cxf.it.com/","MyWebServiceImplService");
Service service=Service.create(url,qname);
MyWebService myWebService=service.getPort(MyWebService.class);
int result=myWebService.add(1,1);
System.out.println(result);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
同上原理差不多,根据QName指定命名空间,已经service节点的实例,在获取对应端口类型进行调用该端口的方法。
调用方式三:
使用js的方式调用,采用的是http的方式。开源项目的地址如下:
https://github.com/doedje/
jQuery.soap