前言
本人从事android开发,基于目前甲方后端使用了Java中WebService技术的现状,不得不在当前项目的结构体系中"掺"入soap请求的实现。
吐槽的话不多说,反正都是泪,干!就完了 . . .
正文
在使用andorid客户端向Java的WebService服务发起请求的过程中;首先能确定的是我们在对接一个特殊[年代久远]类型的服务=>WebService(这玩意.net和java都能实现, 我猜早期的java服务就是从.net上学过来的)其次开始类比我们向JavaWeb服务发起请求的过程:第一我们需要通过http协议向JavaWeb服务发起网络请求(这个我们现如今一般通过OkHttp实现),那么现在我们需要的是通过soap协议向Java.WebService服务发起网络请求(这个我们需要通过ksoap2实现)第二我们需要知道如何与服务进行通信(这个会提供对应的接口文档), 同样的, 那么现在wsdl文档就是我们现在需要的"接口文档".大体的了解了这三个基本概念以后, 我们再来更具体、更详细的介绍一下上面这三个概念(实不相瞒, 上面都是我直觉上的描述)
1. 什么是WebService、什么是SOAP以及什么是WSDL
soap: Simple Object Access Protocol.(简单对象访问协议)wsdl: Web Service Description Language.(Web服务描述语言)
1). 什么是WebService
WebService有着狭义和广义的定义:
广义的来说,WebService就是字面意思:Web+Service,也就是服务(Service)网络(Web)化的意思;它力求的是跨语言和跨平台的、基于Web传输的远程调用能力。
它没有强调远程调用使用什么协议,所以我们可以自由选择,比如SOAP协议或者常见的基于http的json化的数据传输协议。
关于广义的定义更为深入和具体的介绍,可以参看大V阮一峰的这篇博客,就不再过多介绍了:
狭义的来说,我们经常谈的WebService是指基于SOAP协议实现的远程服务调用模型;
2). 什么是SOAP
SOAP定义了数据交互中如何传递消息的规则;
比如在http中规定了post请求的传参方式,在数据类型不同的情况下可以使用不同的参数方式;其中在form格式下是 key=v&key1=v1,同样SOAP也是定义这些东西的;
3). 什么是WSDL
同样的,当我们用http方式去调用一个服务的时候,我们只是知道通用的http协议的传参方式还是不够的,我们仍然需要知道目标服务的接口文档;
对了,这就是WSDL,每个服务都有的接口文档;
在http上可能就是我们手写的一个wiki文档,而在SOAP中就是一个用WSDL规范编写的WSDL文档,每个服务是有能力自动生成这个文档的,其中WSDL规范了这个文档该怎么写;
4). 综上所述
综上所述,SOAP可以类比http协议,WSDL可以类比一个http服务的接口文档;
在了解了WebService、SOAP以及WSDL相关概念以后, 接着我们的目标便是用ksoap2来发起网络请求获取数据了;但是在此之前, 我们首先需要知道我们需要调用接口的详细信息, 也就是如何查看WSDL文档;
2. WSDL文档的基本结构
我们用一个比较常用的天气预报的WebService服务来进行学习:
对应的可视化文档如下:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx
通过这个我们就可以知道WSDL文档的基本结构如下:
<definitions><types>definition of types........数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)</types><message>definition of a message....通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构。</message><portType>definition of a port.......对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持。</portType><binding>definition of a binding....特定端口类型的具体协议和数据格式规范的绑定。</binding><service>相关服务访问点的集合。</servie></definitions>
我们使用getWeatherbyCityName这个接口在总的xml对应的部分做说明,将xml提取出来如下:
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://WebXml.com.cn/"xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"targetNamespace="http://WebXml.com.cn/"><!--types元素:--><wsdl:types><s:schema elementFormDefault="qualified" targetNamespace="http://WebXml.com.cn/"><!--可以看到,types 定义的是数据类型,可以在message元素中进行引用,他的存在形式可能是type也可能是element--><s:complexType name="ArrayOfString"><s:sequence><s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string"/></s:sequence></s:complexType><s:element name="getWeatherbyCityName"><s:complexType><s:sequence><s:element minOccurs="0" maxOccurs="1" name="theCityName" type="s:string"/></s:sequence></s:complexType></s:element><s:element name="getWeatherbyCityNameResponse"><s:complexType><s:sequence><s:element minOccurs="0" maxOccurs="1" name="getWeatherbyCityNameResult"type="tns:ArrayOfString"/></s:sequence></s:complexType></s:element><s:element name="ArrayOfString" nillable="true" type="tns:ArrayOfString"/><s:element name="DataSet" nillable="true"><s:complexType><s:sequence><s:element ref="s:schema"/><s:any/></s:sequence></s:complexType></s:element></s:schema></wsdl:types><!-- message元素: message用来定义每个soap服务的入参和出参,包括参数名,参数类型信息。当引用了types中定义的element元素的时候,name只是有占位意义,并不具备实际的意义 当引用了types中定义的type型元素的时候,name是有意义的,这里的每个message定义并不是针对某个接口的,而是作为基础元素,在portType中描述接口的时候使用。 --><wsdl:message name="getWeatherbyCityNameSoapIn"><!-- name只是有占位意义,并不具备实际的意义 --><wsdl:part name="parameters" element="tns:getWeatherbyCityName"/></wsdl:message><wsdl:message name="getWeatherbyCityNameSoapOut"><wsdl:part name="parameters" element="tns:getWeatherbyCityNameResponse"/></wsdl:message><wsdl:message name="getWeatherbyCityNameHttpGetIn"><!-- name 是有意义的 --><wsdl:part name="theCityName" type="s:string"/></wsdl:message><wsdl:message name="getWeatherbyCityNameHttpGetOut"><wsdl:part name="Body" element="tns:ArrayOfString"/></wsdl:message><wsdl:message name="getWeatherbyCityNameHttpPostIn"><!-- name 是有意义的 --><wsdl:part name="theCityName" type="s:string"/></wsdl:message><wsdl:message name="getWeatherbyCityNameHttpPostOut"><wsdl:part name="Body" element="tns:ArrayOfString"/></wsdl:message><!-- portType 元素: 定义了一个接口的入参和出参,每个portType元素实际上对应了一个接口,就像springMVC当中controller当中定义的一个有@RequestMapping注解的方法一样,他描述了这个方法的入参和出参。 --><wsdl:portType name="WeatherWebServiceSoap"><wsdl:operation name="getWeatherbyCityName"><wsdl:input message="tns:getWeatherbyCityNameSoapIn"/><wsdl:output message="tns:getWeatherbyCityNameSoapOut"/></wsdl:operation></wsdl:portType><wsdl:portType name="WeatherWebServiceHttpGet"><wsdl:operation name="getWeatherbyCityName"><wsdl:input message="tns:getWeatherbyCityNameHttpGetIn"/><wsdl:output message="tns:getWeatherbyCityNameHttpGetOut"/></wsdl:operation></wsdl:portType><wsdl:portType name="WeatherWebServiceHttpPost"><wsdl:operation name="getWeatherbyCityName"><wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">...</wsdl:documentation><wsdl:input message="tns:getWeatherbyCityNameHttpPostIn"/><wsdl:output message="tns:getWeatherbyCityNameHttpPostOut"/></wsdl:operation></wsdl:portType><!-- bingding元素: 仔细观察下面的配置的话可以发现,这几个bingding元素的差异是很大的。 在bingding的第二行说明的是 该bingding使用的协议,是 soap或者soap12 或者是 http-get 或者是 http-post这里的bingding元素对应的type属性标识了对应的portType元素 这里的operation对应了上面对应portType元素中的operation,同时,这里可以岁输入输出做一些处理,比如urlEncoded。use="literal"表示不做特殊处理。 --><wsdl:binding name="WeatherWebServiceSoap" type="tns:WeatherWebServiceSoap"><soap:binding transport="http://schemas.xmlsoap.org/soap/http"/><wsdl:operation name="getWeatherbyCityName"><soap:operation soapAction="http://WebXml.com.cn/getWeatherbyCityName" 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="WeatherWebServiceSoap12" type="tns:WeatherWebServiceSoap"><soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/><wsdl:operation name="getWeatherbyCityName"><soap12:operation soapAction="http://WebXml.com.cn/getWeatherbyCityName" 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="WeatherWebServiceHttpGet" type="tns:WeatherWebServiceHttpGet"><http:binding verb="GET"/><wsdl:operation name="getWeatherbyCityName"><!-- 在http类型中还会增加具体的location信息,这个在对应的http请求里面是可以区分出来的,比如, soap对应的请求是 POST /WebServices/WeatherWebService.asmx HTTP/1.1http-get对应的请求是 GET /WebServices/WeatherWebService.asmx/getWeatherbyCityName?theCityName=string HTTP/1.1 --><http:operation location="/getWeatherbyCityName"/><wsdl:input><http:urlEncoded/></wsdl:input><wsdl:output><mime:mimeXml part="Body"/></wsdl:output></wsdl:operation></wsdl:binding><wsdl:binding name="WeatherWebServiceHttpPost" type="tns:WeatherWebServiceHttpPost"><http:binding verb="POST"/><wsdl:operation name="getWeatherbyCityName"><http:operation location="/getWeatherbyCityName"/><wsdl:input><mime:content type="application/x-www-form-urlencoded"/></wsdl:input><wsdl:output><mime:mimeXml part="Body"/></wsdl:output></wsdl:operation></wsdl:binding><!-- service 元素--><!-- 这里定义的是每个方法具体的访问地址,指向了每个bingding具体绑定的服务地址。 --><wsdl:service name="WeatherWebService"><wsdl:port name="WeatherWebServiceSoap" binding="tns:WeatherWebServiceSoap"><soap:address location="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"/></wsdl:port><wsdl:port name="WeatherWebServiceSoap12" binding="tns:WeatherWebServiceSoap12"><soap12:address location="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"/></wsdl:port><wsdl:port name="WeatherWebServiceHttpGet" binding="tns:WeatherWebServiceHttpGet"><http:address location="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"/></wsdl:port><wsdl:port name="WeatherWebServiceHttpPost" binding="tns:WeatherWebServiceHttpPost"><http:address location="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"/></wsdl:port></wsdl:service></wsdl:definitions>
对应的可视化文档如下:
WeatherWebService Web 服务
www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getWeatherbyCityName 有了接口文档, 我们就能够明确的知道该给服务传递怎样的数据结构了;
根据以上文档,应该向服务传递的请求信息如下( 攫取自getWeatherbyCityName接口的可视化文档 ):
POST /WebServices/WeatherWebService.asmx HTTP/1.1Host: www.webxml.com.cnContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: "http://WebXml.com.cn/getWeatherbyCityName"注*: 所显示的占位符需替换为实际值<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><getWeatherbyCityName xmlns="http://WebXml.com.cn/"><theCityName>string</theCityName></getWeatherbyCityName></soap:Body></soap:Envelope>
响应信息如下( 同上 ):
HTTP/1.1 200 OKContent-Type: application/soap+xml; charset=utf-8Content-Length: length<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><getWeatherbyCityNameResponse xmlns="http://WebXml.com.cn/"><getWeatherbyCityNameResult><string>string</string><string>string</string></getWeatherbyCityNameResult></getWeatherbyCityNameResponse></soap12:Body></soap12:Envelope>
结语
以上我们了解了WebService、SOAP和WSDL的基本概念,在发送网络请求时我们需要借助接口文档,所以我们以getWeatherbyCityName接口为例查看了对应的WSDL文档;并且我们也知道了发送请求时所传递的以及服务响应回来的数据结构;
那么接下来,我们既然已经有了getWeatherbyCityName接口的接口文档,并且知道了请求时的数据结构和入参以及服务响应回来的数据结构,我们就可以通过ksoap来发送网络请求了;
敬请期待 . . .
声明
明眼人能看出来,在定义WebService、SOAP以及WSDL时,不论是介绍基本概念还是所谓的详细说明,都采用了以熟悉的客户端通过http方式请求JavaWeb时类比的方式来介绍的。并没有更加准确和严格的描述。
另外在案例中采用的WSDL也并非严格完整的WSDL文档结构,这个也跟上面提到的没有认知到WSDL严格定义是相关的。
再者所采用的案例中的WSDL文档可能会有所更新,以及后续随着对WSDL的深入了解对其中元素的解释可能会有所改变。
说这么多,无非是想说:从入门来看,这篇文章对基本概念的介绍算是足够了,但是这篇文章的更新迭代并不会结束。
暂无评论数据