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

一、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的服务器地址。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容

  • 概览 CXF frontends 是一组编程的API,被用来开发和发布webservice。CXF支持两种类型的f...
    JohnShen阅读 1,280评论 2 2
  • 因为工作中使用了SOAP进行两个系统的接口调用,所以私下学习一下两种实现,粗略记录于此。本文侧重于实际实现操作,而...
    峡客阅读 4,352评论 0 4
  • 一、Java基础 1.写出下面代码的执行结果 2.写出下面代码的执行结果 3.写出下面代码的执行结果 (此题需写出...
    joshul阅读 509评论 0 1
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,562评论 18 399
  • @你:本文最后有一小碗儿鸡汤,如果你没有增肌需求,又点开了推送,可以直接滑到最下给自己洗洗脑。阅读本文需要3分钟。...
    马克宥阅读 1,206评论 1 6