美文网首页网络通信数据传输
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