美文网首页网络通信数据传输
4、WebService的三个技术基础(WebService笔记

4、WebService的三个技术基础(WebService笔记

作者: yjaal | 来源:发表于2016-06-26 22:02 被阅读1137次

一、WSDL(web service definition lanuage)

首先我们知道在xml文档中,targetName相当于java中的package,而xmlns相当于java中的import
这里我们使用上一个例子(工程WS_Server03)进行说明,首先使用地址http://localhost:8080/myService?wsdl访问可以得到这样一份WebService的实现文档:

<definitions
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"
    xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://impl.ws.cxf.fkjava.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.ws.cxf.fkjava.org/"
    name="HelloWorldWs">
    <import namespace="http://ws.cxf.fkjava.org/" location="http://localhost:8080/myService?wsdl=1" />
    <binding xmlns:ns1="http://ws.cxf.fkjava.org/" name="HelloWorldWsPortBinding"
        type="ns1:HelloWorld">
        <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>
        <operation name="getCatsByUser">
            <soap:operation soapAction="" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
        <operation name="getAllCats">
            <soap:operation soapAction="" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
        </operation>
    </binding>
    <service name="HelloWorldWs">
        <port name="HelloWorldWsPort" binding="tns:HelloWorldWsPortBinding">
            <soap:address location="http://localhost:8080/myService" />
        </port>
    </service>
</definitions>

说明:

  • 1.<definitions>是所有WSDL文档的根元素。其中包括三个子元素:<binding><service><import>
  • 2.<definitions>中的targetNamespace="http://impl.ws.cxf.fkjava.org/" name="HelloWorldWs"表示的是服务端的实现类是HelloWorlds.java,而targetNamespace相当于java中的package
  • 3.<import>子元素用来指定实现类的接口地址。
  • 4.<binding>元素中有N个<operation>子元素,详细定义了每个operationWebService操作)。也就是接口中的所有方法,这里我们定义了三个方法:
String sayHi(String name);
List<Cat> getCatsByUser(User user); 
@XmlJavaTypeAdapter(FkXmlAdapter.class) Map<String, Cat> getAllCats();

这里还使用SOAP定义输入和输出,我们在后面讲。

  • 5.<service>元素中包含<port>子元素,说明WebService绑定的地址。

如果我们使用接口地址http://localhost:8080/myService?wsdl=1访问服务端则会得到下面WebService接口的WSDL文档:

<definitions xmlns:tns="http://ws.cxf.fkjava.org/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/"
    targetNamespace="http://ws.cxf.fkjava.org/">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://ws.cxf.fkjava.org/"
                schemaLocation="http://localhost:8080/myService?xsd=1" />
        </xsd:schema>
    </types>
    <message name="sayHi">
        <part name="parameters" element="tns:sayHi" />
    </message>
    <message name="sayHiResponse">
        <part name="parameters" element="tns:sayHiResponse" />
    </message>
    <message name="getCatsByUser">
        <part name="parameters" element="tns:getCatsByUser" />
    </message>
    <message name="getCatsByUserResponse">
        <part name="parameters" element="tns:getCatsByUserResponse" />
    </message>
    <message name="getAllCats">
        <part name="parameters" element="tns:getAllCats" />
    </message>
    <message name="getAllCatsResponse">
        <part name="parameters" element="tns:getAllCatsResponse" />
    </message>
    <portType name="HelloWorld">
        <operation name="sayHi">
            <input xmlns:ns1="http://www.w3.org/2007/05/addressing/metadata"
                ns1:Action="http://ws.cxf.fkjava.org/HelloWorld/sayHiRequest"
                message="tns:sayHi" />
            <output xmlns:ns2="http://www.w3.org/2007/05/addressing/metadata"
                ns2:Action="http://ws.cxf.fkjava.org/HelloWorld/sayHiResponse"
                message="tns:sayHiResponse" />
        </operation>
        <operation name="getCatsByUser">
            <input xmlns:ns3="http://www.w3.org/2007/05/addressing/metadata"
                ns3:Action="http://ws.cxf.fkjava.org/HelloWorld/getCatsByUserRequest"
                message="tns:getCatsByUser" />
            <output xmlns:ns4="http://www.w3.org/2007/05/addressing/metadata"
                ns4:Action="http://ws.cxf.fkjava.org/HelloWorld/getCatsByUserResponse"
                message="tns:getCatsByUserResponse" />
        </operation>
        <operation name="getAllCats">
            <input xmlns:ns5="http://www.w3.org/2007/05/addressing/metadata"
                ns5:Action="http://ws.cxf.fkjava.org/HelloWorld/getAllCatsRequest"
                message="tns:getAllCats" />
            <output xmlns:ns6="http://www.w3.org/2007/05/addressing/metadata"
                ns6:Action="http://ws.cxf.fkjava.org/HelloWorld/getAllCatsResponse"
                message="tns:getAllCatsResponse" />
        </operation>
    </portType>
</definitions>

说明:

  • 1.这里我们可以看到接口的WSDL文档包含<types>、<message>、<portType>三个子元素。
  • 2.<types>标签是规定接口文档的schema文档,我们使用其地址
    schemaLocation="http://localhost:8080/myService?xsd=1"
    就可以得到其详细文档说明。
  • 3.而接口中一个方法对应两个<message>,因为我们在访问服务端的方法时会有一个发送消息和一个返回消息,于是一般有2N个<message>标签。
  • 4.一次WebService的调用其实并不是方法调用,而是发送SOAP消息(即XML文档片段)。
  • 5.<portType>表示方法接口,里面规定有多少个操作,由子标签<operation>说明。

二、SOAP(Simple Object Access Protocol)简单对象访问协议

接着上面的分析,对于一次sayHi操作来说,传入消息是

<sayHi>
    <arg0>字符串</arg0>
</sayHi>

返回的消息是

<sayHiResponse>
    <return>字符串</return>
</sayHiResponse>

这是通过接口WSDL文档和schema文档得出来的,我们使用地址http://localhost:8080/myService?xsd=1访问可以得到相关的schema文档:

<xs:schema xmlns:tns="http://ws.cxf.fkjava.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0" targetNamespace="http://ws.cxf.fkjava.org/">
    <xs:element name="getAllCats" type="tns:getAllCats" />
    <xs:element name="getAllCatsResponse" type="tns:getAllCatsResponse" />
    <xs:element name="getCatsByUser" type="tns:getCatsByUser" />
    <xs:element name="getCatsByUserResponse" type="tns:getCatsByUserResponse" />
    <xs:element name="sayHi" type="tns:sayHi" />
    <xs:element name="sayHiResponse" type="tns:sayHiResponse" />
    <xs:complexType name="sayHi">
        <xs:sequence>
            <xs:element name="arg0" type="xs:string" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="sayHiResponse">
        <xs:sequence>
            <xs:element name="return" type="xs:string" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="getCatsByUser">
        <xs:sequence>
            <xs:element name="arg0" type="tns:user" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="user">
        <xs:sequence>
            <xs:element name="address" type="xs:string" minOccurs="0" />
            <xs:element name="id" type="xs:int" minOccurs="0" />
            <xs:element name="name" type="xs:string" minOccurs="0" />
            <xs:element name="password" type="xs:string" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="getCatsByUserResponse">
        <xs:sequence>
            <xs:element name="return" type="tns:cat" minOccurs="0"
                maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="cat">
        <xs:sequence>
            <xs:element name="color" type="xs:string" minOccurs="0" />
            <xs:element name="id" type="xs:int" minOccurs="0" />
            <xs:element name="name" type="xs:string" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="getAllCats">
        <xs:sequence />
    </xs:complexType>
    <xs:complexType name="getAllCatsResponse">
        <xs:sequence>
            <xs:element name="return" type="tns:stringCat" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="stringCat">
        <xs:sequence>
            <xs:element name="entries" type="tns:entry" nillable="true"
                minOccurs="0" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="entry">
        <xs:sequence>
            <xs:element name="key" type="xs:string" minOccurs="0" />
            <xs:element name="value" type="tns:cat" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>
</xs:schema>

执行过程是,首先在接口WSDL文档中找到sayHi<message>标签,发现element="tns:sayHi" ,然后在schema文档中找到<xs:element name="sayHi" type="tns:sayHi"/> 进而找到<xs:complexType name="sayHi"> 在这个标签中我们可以看到name="arg0" type="xs:string" minOccurs="0"即参数是arg0,类型是字符串,参数个数最少0个,最多一般没有说明就默认是一个,而如果规定maxOccurs="unbounded" 就表示最多无限多个。于是我们得到发送的XML片段。其他的操作同理。

注意:对于请求是有输入参数的,而没有返回值;对于响应才会有返回值,于是会指定name="arg0"

对于getCatsByUser操作的返回消息:

<getCatsByUserResponse>
    <return>
        <color>字符串</color>
        <id>int</id>
        <name>字符串</name>
    </return>
</getCatsByUserResponse>

但是注意这里的return可以出现无限次,对应我们的返回值List类型。

对于getAllCats操作,是没有输入参数的,但是返回类型较为复杂,我们从schema文档中可以看到分了多个层次进行定义。

注:对于第三大技术基础UUDI现在用处不大。

三、调用一次WebService的本质

  • 1.客户端把调用方法参数,转换成XML文档片段(SOAP消息,input消息)<-->该文档片段符合WSDL定义的格式。

  • 2.通过网络把XML文档片段传给服务器。

  • 3.服务器接收到XML文档片段

  • 4.服务器解析XML文档片段,提取其中的数据,并把数据转换成调用WebService所需的参数值。

  • 5.服务器执行方法。

  • 6.把执行方法得到的返回值再次转换为XML文档片段(SOAP消息,output消息)<-->该文档片段也符合WSDL定义的格式。

  • 7.通过网络把XML文档片段传给客户端。

  • 8.客户端接收到XML文档片段。

  • 9客户端解析XML文档片段,提取其中的数据,并把数据转换成调用WebService所需的返回值。

总结:从上面调用本质来看,要一个语言支持WebService,唯一的要求是该语言支持XML文档解析、生成、支持网络传输。
总的来说,WSDL文档描述如下三个方面:该WebService包含了什么操作;该WebService的操作应该怎样调用;该WebService的服务器地址。

相关文章

网友评论

本文标题:4、WebService的三个技术基础(WebService笔记

本文链接:https://www.haomeiwen.com/subject/giczdttx.html