WSDL 文档是利用这些主要的元素来描述某个 web service 的:
元素 定义<portType> | web service 执行的操作 |
<message> | web service 使用的消息 |
<types> | web service 使用的数据类型 |
<binding> | web service 使用的通信协议 |
下面是一个标准的wsdl定义
来自 http://www.webxml.com.cn/webservices/weatherwebservice.asmx?wsdl
- <?xml version="1.0" encoding="utf-8"?>
- <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 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/" targetNamespace="http://WebXml.com.cn/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
- <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><a href="http://www.webxml.com.cn/" target="_blank">WebXml.com.cn</a> <strong>天气预报 Web 服务,</strong>数据来源于<strong>中国气象局</strong> <a href="http://www.cma.gov.cn/" target="_blank">http://www.cma.gov.cn/</a> ,数据每2.5小时左右自动更新一次,准确可靠。包括 340 多个中国主要城市和 60 多个国外主要城市三日内的天气预报数据。</br>此天气预报Web Services请不要用于任何商业目的,若有需要请<a href="http://www.webxml.com.cn/zh_cn/contact_us.aspx" target="_blank">联系我们</a>,欢迎技术交流。 QQ:8409035<br /><strong>使用本站 WEB 服务请注明或链接本站:http://www.webxml.com.cn/ 感谢大家的支持</strong>!<br /><span style="color:#999999;">通知:天气预报 WEB 服务如原来使用地址 http://www.onhap.com/WebServices/WeatherWebService.asmx 的,请改成现在使用的服务地址 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx ,重新引用即可。</span><br /><br />&nbsp;</wsdl:documentation>
- <wsdl:types>
- <s:schema elementFormDefault="qualified" targetNamespace="http://WebXml.com.cn/">
- <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="getSupportDataSet">
- <s:complexType />
- </s:element>
- <s:element name="getSupportDataSetResponse">
- <s:complexType>
- <s:sequence>
- <s:element minOccurs="0" maxOccurs="1" name="getSupportDataSetResult">
- <s:complexType>
- <s:sequence>
- <s:element ref="s:schema" />
- <s:any />
- </s:sequence>
- </s:complexType>
- </s:element>
- </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>
- <wsdl:message name="getSupportDataSetSoapIn">
- <wsdl:part name="parameters" element="tns:getSupportDataSet" />
- </wsdl:message>
- <wsdl:message name="getSupportDataSetSoapOut">
- <wsdl:part name="parameters" element="tns:getSupportDataSetResponse" />
- </wsdl:message>
- <wsdl:portType name="WeatherWebService">
- <wsdl:operation name="getSupportDataSet">
- <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br><h3>获得本天气预报Web Services支持的洲、国内外省份和城市信息</h3><p>输入参数:无;返回:DataSet 。DataSet.Tables(0) 为支持的洲和国内省份数据,DataSet.Tables(1) 为支持的国内外城市或地区数据。DataSet.Tables(0).Rows(i).Item("ID") 主键对应 DataSet.Tables(1).Rows(i).Item("ZoneID") 外键。<br />Tables(0):IDID = ID主键,Zone = 支持的洲、省份;Tables(1):ID 主键,ZoneID = 对应Tables(0)ID的外键,Area = 城市或地区,AreaCode = 城市或地区代码。</p><br /></wsdl:documentation>
- <wsdl:input message="tns:getSupportDataSetSoapIn" />
- <wsdl:output message="tns:getSupportDataSetSoapOut" />
- </wsdl:operation>
- </wsdl:portType>
- <wsdl:binding name="WeatherWebServiceSoap" type="tns:WeatherWebService">
- <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="getSupportDataSet">
- <soap:operation soapAction="http://WebXml.com.cn/getSupportDataSet" style="document" />
- <wsdl:input>
- <soap:body use="literal" />
- </wsdl:input>
- <wsdl:output>
- <soap:body use="literal" />
- </wsdl:output>
- </wsdl:operation>
- </wsdl:binding>
- <wsdl:service name="WeatherWebService">
- <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><a href="http://www.webxml.com.cn/" target="_blank">WebXml.com.cn</a> <strong>天气预报 Web 服务,</strong>数据来源于<strong>中国气象局</strong> <a href="http://www.cma.gov.cn/" target="_blank">http://www.cma.gov.cn/</a> ,数据每2.5小时左右自动更新一次,准确可靠。包括 340 多个中国主要城市和 60 多个国外主要城市三日内的天气预报数据。</br>此天气预报Web Services请不要用于任何商业目的,若有需要请<a href="http://www.webxml.com.cn/zh_cn/contact_us.aspx" target="_blank">联系我们</a>,欢迎技术交流。 QQ:8409035<br /><strong>使用本站 WEB 服务请注明或链接本站:http://www.webxml.com.cn/ 感谢大家的支持</strong>!<br /><span style="color:#999999;">通知:天气预报 WEB 服务如原来使用地址 http://www.onhap.com/WebServices/WeatherWebService.asmx 的,请改成现在使用的服务地址 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx ,重新引用即可。</span><br /><br />&nbsp;</wsdl:documentation>
- <wsdl:port name="WeatherWebService" binding="tns:WeatherWebServiceSoap">
- <soap:address location="http://www.webxml.com.cn/webservices/weatherwebservice.asmx" />
- </wsdl:port>
- </wsdl:service>
- </wsdl:definitions>
自己做的项目中用axis2做webservice, 并与spring集成,
这个集成方法比较麻烦, 找到了更简便的方法 http://renxiangzyq.iteye.com/blog/1021696
之前已经集成了,下面是我找到的一些集成点
web.xml
- <servlet>
- <servlet-name>AxisServlet</servlet-name>
- <servlet-class>org.apache.axis2.transport.http.AxisServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>AxisServlet</servlet-name>
- <url-pattern>/services/*</url-pattern><!--have to named as /services/-->
- </servlet-mapping>
WEB-INF 下的相关目录
- .
- ├── conf
- │ └── axis2.xml
- ├── modules
- │ ├── addressing-1.5.2.mar
- │ ├── axis2-jaxws-mar-1.5.2.mar
- │ ├── mex-1.5.2.mar
- │ ├── modules.list
- │ ├── mtompolicy-1.5.2.mar
- │ ├── ping-1.5.2.mar
- │ ├── scripting-1.5.2.mar
- │ └── soapmonitor-1.5.2.mar
- ├── services
- │ ├── ecvservice
- │ │ └── META-INF
- │ │ └── services.xml
- │ ├── services.list
- │ └── version-1.5.2.aar
- └── web.xml
接下来我要新加一个webservice
1. 首先用myeclipse的New。。。 里面wsdl生成一个wsdl模板, 然后自己在wsdl可视化设计器里定义输入, 输出
这里要注意的是定义复杂类型是在设计器的一个叫types 的地方, 或者直接写source, 下面是个列子
- <wsdl:types>
- <xs:schema xmlns:ax23="http://webservice.xxxx.com" xmlns:ax24="http://webservice.xxxx.com/xsd" xmlns:ax22="http://business.webservice.xxxx.com/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://webservice.xxxx.com">
- <xs:complexType name="Entrydata">
- <xs:sequence>
- <xs:element minOccurs="0" name="authToken" nillable="true" type="xs:string"/>
- <xs:element minOccurs="0" name="url" nillable="true" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- <xs:complexType name="Result">
- <xs:sequence>
- <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/>
- <xs:element minOccurs="0" name="status" nillable="true" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- <xs:element name="getAuthToken">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="userName" nillable="true" type="xs:string"/>
- <xs:element minOccurs="0" name="userId" nillable="true" type="xs:string"/>
- <xs:element minOccurs="0" name="friendlyName" nillable="true" type="xs:string"/>
- <xs:element minOccurs="0" name="email" nillable="true" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="getAuthTokenResponse">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="entrydata" nillable="true" type="ax23:Entrydata"/>
- <xs:element minOccurs="0" name="result" nillable="true" type="ax23:Result"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:schema>
- </wsdl:types>
2. 在wsdl写好后就可以利用axis2的plugin来生成代码,可以生成服务器端和客户端的, 我主要是要服务器端的,把服务器端的代码copy要到项目中,
- ├── AserviceMessageReceiverInOut.java //输入 输出 的转换对象
- ├── AserviceSkeleton.java //service类
- ├── AserviceSkeletonInterface.java //接口
- ├── AuthRequest.java //代表请求数据的类 负责请求数据的处理
- ├── AuthResponse.java //响应数据的类 负责响应数据
- ├── Entrydata.java //复杂数据类型
- ├── ExtensionMapper.java //不用管的
- └── Result.java //复杂数据类型
然后把│ ├── aservice
- │ │ └── META-INF
- │ │ └── services.xml
放入WEB-INF/services/下
service.xml 内容如下
- <?xml version="1.0" encoding="UTF-8"?>
- <service name="aservice">
- <description>atservice - spring axis2 web service</description>
- <parameter name="ServiceObjectSupplier">org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier</parameter>
- <parameter name="SpringBeanName">aWebService</parameter>
- <messageReceivers >
- <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out" class="com.xxxx.webservice.AserviceMessageReceiverInOut"/>
- </messageReceivers>
- </service>
3. 接着启动服务器 访问 /services/aservice?wsdl 应该就可以看到wsdl , 但这个wsdl和原来里自己写的有些不一样了
你可能想自己修改(服务器生成的可能格式不对, 用soapui不能直接访问) , 可以把这个生成的wsdl 保存到一个文件中放到 WEB-INF/services/aservice/META-INF/下,然后自己按照想要的修改, 这个时候在去访问/services/aservice?wsdl看到的就是你自己修改过的了,
(但这里面的location会根据你访问的地址变化, 所以就不用担心wsdl里面的一些写死的地址相关的会在开发服务器和生产服务器切换的时候要去修改配置了)
如
- <soap:address
- location="http://127.0.0.1:8080/xxxx/services/aservice.aserviceHttpSoap11Endpoint/" />
是你访问127.0.0.1时的输出
- <soap:address
- location="http://localhost:8080/xxxx/services/aservice.aserviceHttpSoap11Endpoint/" />
是你访问localhost时的输出
最后完成的目标应该是soapui直接用访问 /services/aservice?wsdl生成的wsdl生成一个项目, 然后直接用默认的request可以去访问服务而不出异常
最开始的时候会报错
因为AuthRequest.java里面有句
- if (reader.isStartElement() && new javax.xml.namespace.QName("", "userName").equals(reader.getName())) {
这里是两个QName做比较, 服务器端生成的
- new javax.xml.namespace.QName("", "userName")
是没有namespace 的, 而客户端请求上来的是有namespace 的, 所以会出现Unexpected subelement
这里我在比较的时候加了QName.getLocalPart()去比较 就忽略了namespace对比较的影响
还有一个关于namespace 的讨论
http://grails.1312388.n4.nabble.com/Grails-AXIS2-Web-Services-td3452513.html