原文链接: http://www.kylin-ux.com/2017/04/21/network-web-web-service系列之数组参数
概要 本文主要关注web service接口参数为数组 的场景, 比较JAX-WS与spyne的区别
说明, 本文中JAX-WS指基于JAX-WS实现的web service服务器, spyne指基于spyne实现的web service服务器
实例代码见:http://www.kylin-ux.com/2017/04/21/network-web-web-service系列之实例之JAX-WS http://www.kylin-ux.com/2017/04/21/network-web-web-service系列之实例之spyne
client代码片断 zeep/suds访问JAX-WS1
r = client.service.helloWorld(['Kylin', 'Shu'])
zeep访问spyne1
2
3
factory = client.type_factory("ns0")
names = factory.stringArray(["Kylin", "Shu"])
r = client.service.say_hello_plus2(names)
suds访问spyne1
2
3
4
names = client.factory.create("stringArray")
names.string.append("Kylin")
names.string.append("Shu")
r = client.service.say_hello_plus2(names)
helloWorld接口和say_hello_plus2接口参数均为字符串数组 访问spyne接口需要创建stringArray
类型 文章JAX-WS接口则不需要
报文分析 向JAX-WS请求类型的回复报文片断1
2
3
4
5
<xs:complexType name="helloWorld">
<xs:sequence>
<xs:element name="arg0" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
向spyne请求类型的回复报文片断1
2
3
4
5
<xs:complexType name="stringArray">
<xs:sequence>
<xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</xs:sequence>
</xs:complexType>
注意: JAX-WS, <xs:complexType name="**helloWorld**"> <xs:element name="arg0">
spyne, <xs:complexType name="stringArray"> <xs:element name="string">
helloWorld 为接口名
向JAX-WS请求接口报文1
2
3
4
5
6
7
8
9
10
Ej4@@#(v|%Rw^
3I3I<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:helloWorld xmlns:ns0="http://webservice.kylinux.com/">
<arg0>Kylin</arg0>
<arg0>Shu</arg0>
</ns0:helloWorld>
</soap-env:Body>
</soap-env:Envelope>
1
2
3
4
E9@@.#(%Sv~*w-
3I3Ifa
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:helloWorldResponse xmlns:ns2="http://webservice.kylinux.com/"><return>Hello world from KylinShu</return></ns2:helloWorldResponse></S:Body></S:Envelope>
0
向spyne请求接口报文1
2
3
4
5
6
7
8
9
10
11
12
13
EB@@m@E0
R^V
:#r:#r<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:say_hello_plus2 xmlns:ns0="spyne.examples.hello.soap">
<ns0:name_plus>
<ns0:string>Kylin</ns0:string>
<ns0:string>Shu</ns0:string>
</ns0:name_plus>
</ns0:say_hello_plus2>
</soap-env:Body>
</soap-env:Envelope>
1
2
3
4
5
6
7
8
9
10
EMq.@@z@0
R^gB
:#t:#rHTTP/1.0 200 OK
Date: Fri, 21 Apr 2017 07:04:23 GMT
Server: WSGIServer/0.2 CPython/3.5.2
Content-Type: text/xml; charset=utf-8
Content-Length: 383
<?xml version='1.0' encoding='UTF-8'?>
<soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="spyne.examples.hello.soap"><soap11env:Body><tns:say_hello_plus2Response><tns:say_hello_plus2Result><tns:string>Kylin</tns:string><tns:string>Shu</tns:string></tns:say_hello_plus2Result></tns:say_hello_plus2Response></soap11env:Body></soap11env:Envelope>
spyne比JAX-WS多了一层嵌套<ns0:name_plus> ... </ns0:name_plus>
附wireshark抓包结果 zeep client调用JAX-WS helloWorld接口, 通过wireshark抓取部分报文 请求wsdl1
2
3
4
5
6
7
E3@@#(vz%EV
3I[3I[GET /WS/HelloWorld?wsdl HTTP/1.1
Host: 127.0.0.1:9000
Accept-Encoding: gzip, deflate
User-Agent: Zeep/1.4.1 (www.python-zeep.org)
Connection: keep-alive
Accept: */*
1
2
3
4
5
6
7
8
9
E@@'i#(%F
v{Q^
3I\3I\885
<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><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://webservice.kylinux.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://webservice.kylinux.com/" name="HelloWorldImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://webservice.kylinux.com/" schemaLocation="http://127.0.0.1:9000/WS/HelloWorld?xsd=1"></xsd:import>
</xsd:schema>
</types>
1
2
3
4
5
6
<message name="helloWorld">
<part name="parameters" element="tns:helloWorld"></part>
</message>
<message name="helloWorldResponse">
<part name="parameters" element="tns:helloWorldResponse"></part>
</message>
1
2
3
4
5
6
<portType name="HelloWorld">
<operation name="helloWorld">
<input wsam:Action="http://webservice.kylinux.com/HelloWorld/helloWorldRequest" message="tns:helloWorld"></input>
<output wsam:Action="http://webservice.kylinux.com/HelloWorld/helloWorldResponse" message="tns:helloWorldResponse"></output>
</operation>
</portType>
1
2
3
4
5
6
7
8
9
10
11
12
<binding name="HelloWorldImplPortBinding" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
<operation name="helloWorld">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
</operation>
</binding>
1
2
3
4
5
6
<service name="HelloWorldImplService">
<port name="HelloWorldImplPort" binding="tns:HelloWorldImplPortBinding">
<soap:address location="http://127.0.0.1:9000/WS/HelloWorld"></soap:address>
</port>
</service>
</definitions>
请求类型1
2
3
4
5
6
7
E3@@#(v{Q%NU
3I^3I\GET /WS/HelloWorld?xsd=1 HTTP/1.1
Host: 127.0.0.1:9000
Accept-Encoding: gzip, deflate
User-Agent: Zeep/1.4.1 (www.python-zeep.org)
Connection: keep-alive
Accept: */*
1
2
3
E@@,#(%Ov{g
3I3I367
<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<xs:schema xmlns:tns="http://webservice.kylinux.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://webservice.kylinux.com/">
<xs:element name="helloWorld" type="tns:helloWorld"></xs:element>
<xs:element name="helloWorldResponse" type="tns:helloWorldResponse"></xs:element>
<xs:complexType name="helloWorld">
<xs:sequence>
<xs:element name="arg0" type="xs:string" nillable="true" minOccurs="0" maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="helloWorldResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
0
zeep client调用spyne say_hello_plus2接口, 通过wireshark抓取部分报文, 请求wsdl1
2
3
4
5
6
7
E@@@T{V
:#^:#^GET /?wsdl HTTP/1.1
Host: 127.0.0.1:8000
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Zeep/1.4.1 (www.python-zeep.org)
Connection: keep-alive
回复内容概要1
2
3
4
5
6
7
8
9
10
11
12
<wsdl:types>...</wsdl:types>
<wsdl:message name="say_hello">...</wsdl:message>
<wsdl:message name="say_helloResponse">...</wsdl:message>
<wsdl:message name="say_hello_plus">...</wsdl:message>
<wsdl:message name="say_hello_plusResponse">...</wsdl:message>
<wsdl:message name="say_hello_plus2">...</wsdl:message>
<wsdl:message name="say_hello_plus2Response">...</wsdl:message>
<wsdl:service name="HelloWorldService">...</wsdl:service>
<wsdl:service name="HelloWorldService2">...</wsdl:service>
<wsdl:portType name="Application">...</wsdl:portType>
<wsdl:binding name="Application" type="tns:Application">...</wsdl:binding>
</wsdl:definitions>
回复详细内容1
2
3
4
5
6
7
8
9
E@@eu@{^
:#e:#^HTTP/1.0 200 OK
Date: Fri, 21 Apr 2017 07:04:23 GMT
Server: WSGIServer/0.2 CPython/3.5.2
Content-Type: text/xml; charset=utf-8
Content-Length: 6162
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions xmlns:plink="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap11enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap12enc="http://www.w3.org/2003/05/soap-encoding" xmlns:soap12env="http://www.w3.org/2003/05/soap-envelope" xmlns:tns="spyne.examples.hello.soap" xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="spyne.examples.hello.soap" name="Application">
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<wsdl:types>
<xs:schema targetNamespace="spyne.examples.hello.soap" elementFormDefault="qualified">
<xs:complexType name="stringArray">
<xs:sequence>
<xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Name">
<xs:sequence>
<xs:element name="first_name" type="xs:string" minOccurs="0" nillable="true"/>
<xs:element name="last_name" type="xs:string" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<xs:complexType name="say_hello">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" nillable="true"/>
<xs:element name="times" type="xs:integer" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="say_hello_plus">
<xs:sequence>
<xs:element name="name_plus" type="tns:NameArray" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="say_hello_plus2">
<xs:sequence>
<xs:element name="name_plus" type="tns:stringArray" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<xs:complexType name="say_helloResponse">
<xs:sequence>
<xs:element name="say_helloResult" type="tns:stringArray" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="say_hello_plus2Response">
<xs:sequence>
<xs:element name="say_hello_plus2Result" type="tns:stringArray" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="say_hello_plusResponse">
<xs:sequence>
<xs:element name="say_hello_plusResult" type="tns:stringArray" minOccurs="0" nillable="true"/>
</xs:sequence>
</xs:complexType>
1
2
3
4
5
<xs:complexType name="NameArray">
<xs:sequence>
<xs:element name="Name" type="tns:Name" minOccurs="0" maxOccurs="unbounded" nillable="true"/>
</xs:sequence>
</xs:complexType>
1
2
3
4
5
6
7
8
9
10
11
<xs:element name="stringArray" type="tns:stringArray"/>
<xs:element name="Name" type="tns:Name"/>
<xs:element name="say_hello" type="tns:say_hello"/>
<xs:element name="say_hello_plus2" type="tns:say_hello_plus2"/>
<xs:element name="say_hello_plus2Response" type="tns:say_hello_plus2Response"/>
<xs:element name="say_hello_plusResponse" type="tns:say_hello_plusResponse"/>
<xs:element name="NameArray" type="tns:NameArray"/>
<xs:element name="say_helloResponse" type="tns:say_helloResponse"/>
<xs:element name="say_hello_plus" type="tns:say_hello_plus"/>
</xs:schema>
</wsdl:types>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<wsdl:message name="say_hello">
<wsdl:part name="say_hello" element="tns:say_hello"/>
</wsdl:message>
<wsdl:message name="say_helloResponse">
<wsdl:part name="say_helloResponse" element="tns:say_helloResponse"/>
</wsdl:message>
<wsdl:message name="say_hello_plus">
<wsdl:part name="say_hello_plus" element="tns:say_hello_plus"/>
</wsdl:message>
<wsdl:message name="say_hello_plusResponse">
<wsdl:part name="say_hello_plusResponse" element="tns:say_hello_plusResponse"/>
</wsdl:message>
<wsdl:message name="say_hello_plus2">
<wsdl:part name="say_hello_plus2" element="tns:say_hello_plus2"/>
</wsdl:message>
<wsdl:message name="say_hello_plus2Response">
<wsdl:part name="say_hello_plus2Response" element="tns:say_hello_plus2Response"/>
</wsdl:message>
1
<wsdl:service name="HelloWorldService"><wsdl:port name="Application" binding="tns:Application"><soap:address location="http://127.0.0.1:8000/"/></wsdl:port></wsdl:service><wsdl:service name="HelloWorldService2"><wsdl:port name="Application" binding="tns:Application"><soap:address location="http://127.0.0.1:8000/"/></wsdl:port></wsdl:service>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<wsdl:portType name="Application">
<wsdl:operation name="say_hello" parameterOrder="say_hello">
<wsdl:documentation>Docstrings for service methods appear as documentation in the wsdl.
<b>What fun!</b>
@param name the name to say hello to
@param times the number of times to say hello
@return the completed array
</wsdl:documentation>
<wsdl:input name="say_hello" message="tns:say_hello"/>
<wsdl:output name="say_helloResponse" message="tns:say_helloResponse"/>
</wsdl:operation>
<wsdl:operation name="say_hello_plus" parameterOrder="say_hello_plus">
<wsdl:input name="say_hello_plus" message="tns:say_hello_plus"/>
<wsdl:output name="say_hello_plusResponse" message="tns:say_hello_plusResponse"/>
</wsdl:operation>
<wsdl:operation name="say_hello_plus2" parameterOrder="say_hello_plus2">
<wsdl:input name="say_hello_plus2" message="tns:say_hello_plus2"/>
<wsdl:output name="say_hello_plus2Response" message="tns:say_hello_plus2Response"/>
</wsdl:operation>
</wsdl:portType>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<wsdl:binding name="Application" type="tns:Application">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="say_hello">
<soap:operation soapAction="say_hello" style="document"/>
<wsdl:input name="say_hello"><soap:body use="literal"/></wsdl:input>
<wsdl:output name="say_helloResponse"><soap:body use="literal"/></wsdl:output>
</wsdl:operation>
<wsdl:operation name="say_hello_plus">
<soap:operation soapAction="say_hello_plus" style="document"/>
<wsdl:input name="say_hello_plus"><soap:body use="literal"/></wsdl:input>
<wsdl:output name="say_hello_plusResponse"><soap:body use="literal"/></wsdl:output>
</wsdl:operation>
<wsdl:operation name="say_hello_plus2">
<soap:operation soapAction="say_hello_plus2" style="document"/>
<wsdl:input name="say_hello_plus2"><soap:body use="literal"/></wsdl:input>
<wsdl:output name="say_hello_plus2Response"><soap:body use="literal"/></wsdl:output>
</wsdl:operation>
</wsdl:binding>