wsdl(网络服务描述语言,Web Services Description Language)是一门基于XML的语言,用于描述Web Services以及如何对它进行访问。
wsdl由六个部分组成,都在<definitions>根节点之下
元素 | 定义 |
<portType> | Web service的抽象接口,类似于一个在java或c#中定义的接口。如果你想快速理解一个web service所提供的功能,看这个部分的内容即可。 |
<message> | Web service所使用的消息。 |
<types> | Web service所需要使用到的数据类型,这些数据类型用xml schema元素列表示 |
<binding> | 描述了portType如何被映射到具体的数据格式或协议 |
<port> | 描述服务的端点(endpoint)的部署信息,简单的说,就是描述了可以找到此服务的url |
<service> | 是一个port元素的集合,通过它,可以指定一个web service在多个端点上发布 |
一个wsdl文档的主要结构是类似这样的:
<definitions>
<types>
definition of types...
</types>
<message>
definition of message...
</message>
<portType>
definition of port...
</portType>
<binding>
definition of binding...
</binding>
<service>
<port>...</port>
<port>...</port>
</service>
</definitions>
1.1 命名空间
命名空间是用于分类和归类XML文档中的元素、数据类型以及属性名的一种方法。XML命名空间类似于java的package和c#的namespace关键字,用于解决命名冲突。举例如下
<!--shipping.xsd-->
<complexType name="Address">
<sequence>
<element name="street" type="string" minOccurs="1"/>
<element name="city" type="string" minOccurs="1" maxOccurs="1"/>
<element name="state" type="string" minOccurs="1" maxOccurs="1"/>
<element name="zipCode" type="string" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
<!--customer.xsd-->
<complexType name="Address">
<sequence>
<element name="street1" type="string" minOccurs="1" maxOccurs="1"/>
<element name="street2" type="string" minOccurs="1" maxOccurs="1"/>
<element name="street3" type="string" minOccurs="1" maxOccurs="1"/>
<element name="city" type="string" minOccurs="1" maxOccurs="1"/>
<element name="state" type="string" minOccurs="1" maxOccurs="1"/>
<element name="zipCode" type="string" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
<!--order.wsdl-->
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap"
xmlns:tns="http://www.alsb.com/sample"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="Sample"
xmlns:shp="http://www.alsb.com/shipping"
xmlns:customer="http://www.alsb.com/customer"
targetNamespace="http://www.alsb.com/order/">
<wsdl:types>
<xsd:schema targetNamespace="http://www.alsb.com/customer">
<xsd:element name="CustomerAddress" type="customer:Address"></xsd:element>
<xsd:element name="ShippingAddress" type="shp:Address"></xsd:element>
</xsd:schema>
</wsdl:types>
</wsdl:definitions>
从上面的例子可以看出,为了使“Address”不冲突,引入了命名空间来加以区分。
1.2 <types>
wsdl使用xml schema来定义数据类型。Xml schema提供了相当多的本地数据类型(string, integer, date, time...);例如声明一个string类型的对象,可以这样做:
<element name="MyString" type="string"/>
可以通过本地数据类型来组合自定义一些复杂数据类型,如前一节提到的两个Address数据类型定义。minOccurs规定一个元素在sequence中出现的最小次数,如果为0表示该元素的出现是可选的;maxOccours是对minOccurs的一个补充,指定元素在sequence中出现的最大次数,maxOccours的值必须大于0,或者设为unbound。
当需要使用外部定义好的xml schema,需要先导入到当前wsdl文档中。例如前一节提到的,将shipping.xsd和customer.xsd导入到order.wsdl中需要如下的语句:
<xs:import namespace="http://www.alsb.com/customer" shcemaLocation="customer.xsd" />
<xs:import namespace="http://www.alsb.com/shipping" shcemaLocation="shipping.xsd" />
1.3 <message>
消息(message)描述了输入、输出以及错误信息的基本形式。消息是由一个或多个<part>元素组成的,这些<part>元素描述了<message>的成分。
<wsdl:message>
<wsdl:part element="tns:getCustomerResponse" name="customer"/>
</wsdl:message>
1.4 <portType>
wsdl的portType部分描述了web service的抽象接口。在wsdl中,这个部分可以类比为java的抽象接口,因为它从更高层次定义了操控服务的方法(即需要什么参数,以及返回什么结果)。
<portType>元素是由多个<operation>元素组成的。这些<operation>则是由一些对应的<message>元素的<input>和<output>元素组成。<operation>元素可能包含<fault>元素,以用于显示操作中可能抛出的soap错误。
<wsdl:portType name="CustomerPortType">
<wsdl:operation name="findCustomer">
<wsdl:input message="tns:findCustomer" />
<wsdl:output message="tns:findCustomerResponse"/>
</wsdl:operation>
</wsdl:portType>
1.5 <binding>
<binding>用于定义<portType>(即web service的抽象接口)如何被绑定到一个传输协议和一个编码(encoding)配置上。一个单独的<portType>可以被绑定到多个由transport和encoding shcema组合配置上。
<wsdl:bingding name="CustomerServiceSoap" type="tns:CustomerPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="findCustomer">
<soap:operation soapAction="" style="document" />
<wsdl:input>
<soap:body parts="findCustomer" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body parts="findCustomerResponse" use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
1.6 <service>
一个服务<service>简单来说就是一组<port>元素的集合。一个wsdl可能包括了多个<service>定义,每一个定义对应web service所支持的不同binding类型。
1.7 <port>
<port>描述了binding的物理位置。
<wsdl:service name="CustomerService">
<wsdl:port binding="tns:CustomerServiceSoap" name="CustomerServiceSoap">
<soap:address location="http://server1:7001/customer/CustomerService" />
<soap:address location="http://server2:7001/customer/CustomerService" />
</wsdl:port>
</wsdl:service>
上面的例子显示了一个web service的例子,它存在于两个不同的端点上。端点(Endpoint)简单来说就是一个指向某个服务所在物理位置的URI。
1.8 两个完整的例子
<?xml version="1.0" encoding="UTF-8"?>
<!-- hello.wsdl -->
<wsdl:definitions targetNamespace="http://192.168.34.41:9090/axis2/services/hello"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://192.168.34.41:9090/axis2/services/hello"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- 定义了两个数据类型作为greetX的输入参数和输出参数 -->
<wsdl:types>
<schema elementFormDefault="qualified"
targetNamespace="http://192.168.34.41:9090/axis2/services/hello"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://192.168.34.41:9090/axis2/services/hello"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<element name="greetRequest">
<complexType>
<sequence>
<element name="greetInput" type="xsd:string" />
</sequence>
</complexType>
</element>
<element name="greetResponse">
<complexType>
<sequence>
<element name="greetReturn" type="xsd:string" />
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<!-- 使用上面定义的数据类型,为每一个接口方法定义了输入输出消息 -->
<wsdl:message name="greetResponse1">
<wsdl:part element="impl:greetResponse" name="parameters" />
</wsdl:message>
<wsdl:message name="greetRequest1">
<wsdl:part element="impl:greetRequest" name="parameters" />
</wsdl:message>
<wsdl:message name="greetResponse2">
<wsdl:part element="impl:greetResponse" name="parameters" />
</wsdl:message>
<wsdl:message name="greetRequest2">
<wsdl:part element="impl:greetRequest" name="parameters" />
</wsdl:message>
<wsdl:message name="greetResponse3">
<wsdl:part element="impl:greetResponse" name="parameters" />
</wsdl:message>
<wsdl:message name="greetRequest3">
<wsdl:part element="impl:greetRequest" name="parameters" />
</wsdl:message>
<!-- 定义接口,指定接口名称、使用的输入输出消息 -->
<wsdl:portType name="hello">
<wsdl:operation name="greet1">
<wsdl:input message="impl:greetRequest1" name="greetRequest1" />
<wsdl:output message="impl:greetResponse1" name="greetResponse1" />
</wsdl:operation>
<wsdl:operation name="greet2">
<wsdl:input message="impl:greetRequest2" name="greetRequest2" />
<wsdl:output message="impl:greetResponse2" name="greetResponse2" />
</wsdl:operation>
<wsdl:operation name="greet3">
<wsdl:input message="impl:greetRequest3" name="greetRequest3" />
<wsdl:output message="impl:greetResponse3" name="greetResponse3" />
</wsdl:operation>
</wsdl:portType>
<!-- 指定传输协议和编码 -->
<wsdl:binding name="HelloSoapBinding" type="impl:hello">
<wsdlsoap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="greet1">
<wsdlsoap:operation soapAction="hello#greet1" />
<wsdl:input name="greetRequest1">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="greetResponse1">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="greet2">
<wsdlsoap:operation soapAction="hello#greet2" />
<wsdl:input name="greetRequest2">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="greetResponse2">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="greet3">
<wsdlsoap:operation soapAction="hello#greet3" />
<wsdl:input name="greetRequest3">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="greetResponse3">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!-- 定义服务 -->
<wsdl:service name="hello">
<wsdl:port binding="impl:HelloSoapBinding" name="hello">
<wsdlsoap:address location="http://192.168.34.41:9090/axis2/services/hello" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
<?xml version="1.0" encoding="UTF-8"?>
<!-- PersonInfoService.wsdl -->
<wsdl:definitions
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ns1="http://org.apache.axis2/xsd"
xmlns:ns="http://samples.esb.wso2.org"
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:ax21="http://samples.esb.wso2.org/xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
targetNamespace="http://samples.esb.wso2.org">
<wsdl:documentation>PersonInfoService</wsdl:documentation>
<wsdl:types>
<xs:schema xmlns:ax22="http://samples.esb.wso2.org/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://samples.esb.wso2.org">
<xs:import namespace="http://samples.esb.wso2.org/xsd" />
<xs:element name="get">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="id" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="return" nillable="true" type="ax21:PersonInfo" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://samples.esb.wso2.org/xsd">
<xs:complexType name="PersonInfo">
<xs:sequence>
<xs:element minOccurs="0" name="address" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="id" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="name" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="getRequest">
<wsdl:part name="parameters" element="ns:get" />
</wsdl:message>
<wsdl:message name="getResponse">
<wsdl:part name="parameters" element="ns:getResponse" />
</wsdl:message>
<wsdl:portType name="PersonInfoServicePortType">
<wsdl:operation name="get">
<wsdl:input message="ns:getRequest" wsaw:Action="urn:get" />
<wsdl:output message="ns:getResponse" wsaw:Action="urn:getResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="PersonInfoServiceSoap11Binding" type="ns:PersonInfoServicePortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<wsdl:operation name="get">
<soap:operation soapAction="urn:get" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="PersonInfoServiceSoap12Binding" type="ns:PersonInfoServicePortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<wsdl:operation name="get">
<soap12:operation soapAction="urn:get" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="PersonInfoServiceHttpBinding" type="ns:PersonInfoServicePortType">
<http:binding verb="POST" />
<wsdl:operation name="get">
<http:operation location="get" />
<wsdl:input>
<mime:content type="text/xml" part="parameters" />
</wsdl:input>
<wsdl:output>
<mime:content type="text/xml" part="parameters" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="PersonInfoService">
<wsdl:port name="PersonInfoServiceHttpsSoap11Endpoint" binding="ns:PersonInfoServiceSoap11Binding">
<soap:address location="https://10.215.26.81:9443/services/PersonInfoService.PersonInfoServiceHttpsSoap11Endpoint/" />
</wsdl:port>
<wsdl:port name="PersonInfoServiceHttpSoap11Endpoint" binding="ns:PersonInfoServiceSoap11Binding">
<soap:address location="http://10.215.26.81:9763/services/PersonInfoService.PersonInfoServiceHttpSoap11Endpoint/" />
</wsdl:port>
<wsdl:port name="PersonInfoServiceHttpSoap12Endpoint" binding="ns:PersonInfoServiceSoap12Binding">
<soap12:address location="http://10.215.26.81:9763/services/PersonInfoService.PersonInfoServiceHttpSoap12Endpoint/" />
</wsdl:port>
<wsdl:port name="PersonInfoServiceHttpsSoap12Endpoint" binding="ns:PersonInfoServiceSoap12Binding">
<soap12:address location="https://10.215.26.81:9443/services/PersonInfoService.PersonInfoServiceHttpsSoap12Endpoint/" />
</wsdl:port>
<wsdl:port name="PersonInfoServiceHttpsEndpoint" binding="ns:PersonInfoServiceHttpBinding">
<http:address location="https://10.215.26.81:9443/services/PersonInfoService.PersonInfoServiceHttpsEndpoint/" />
</wsdl:port>
<wsdl:port name="PersonInfoServiceHttpEndpoint" binding="ns:PersonInfoServiceHttpBinding">
<http:address location="http://10.215.26.81:9763/services/PersonInfoService.PersonInfoServiceHttpEndpoint/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>