实验目的:安装jdk1.6_21以后的版本,利用JAX-WS API自己发布webservice并调用,以及用wsimport生成webservice客户端代码调用一个免费的web服务(如webxml.com.cn上的获取手机归属地的服务)。
一、webservice原理了解
webservice是一种通用的跨语言跨平台的数据交互方式,之所以能够做到这一点,是因为它的底层实现机制是依赖于HTTP协议以及XML格式这些开发的标准。webservice使用SOAP(simple object access protocol)协议来传送请求和响应消息,使用WSDL(webservice description language)来描述发布的服务。其中,
1)SOAP=在HTTP的基础上+XML数据,按照规范,SOAP的组成有:
Envelope:必须,xml数据的根元素
Headers:可选
Body:必须,包含要执行的服务的方法和发送到服务器的数据
SOAP的请求(本质上认识POST方式的HTTP请求)类似于如下:
POST /WebServices/MobileCodeWS.asmx HTTP/1.1 Host: webservice.webxml.com.cn Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "http://WebXml.com.cn/getMobileCodeInfo" <?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> <getMobileCodeInfo xmlns="http://WebXml.com.cn/"> <mobileCode>18212124343</mobileCode> <userID>null</userID> </getMobileCodeInfo> </soap:Body> </soap:Envelope>
SOAP的响应信息类似如下:
HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: 3223 <?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> <getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/"> <getMobileCodeInfoResult>18212124343:上海 上海 上海移动全球通卡</getMobileCodeInfoResult> </getMobileCodeInfoResponse> </soap:Body> </soap:Envelope>
2)WSDL主要是给服务调用者看的,说明了服务的地址和端口,以及提供的方法和参数信息。由于WSDL规范,我们也可以使用JDK1.6以后提供的wsimport工具生长webservice调用的客户端代码,以简化webservice的调用。
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>,提供最新的国内手机号码段归属地数据,每月更新。<br />使用本站 WEB 服务请注明或链接本站:<a href="http://www.webxml.com.cn/" target="_blank">http://www.webxml.com.cn/</a> 感谢大家的支持!<br />&nbsp;</wsdl:documentation> <wsdl:types> <s:schema elementFormDefault="qualified" targetNamespace="http://WebXml.com.cn/"> <s:element name="getMobileCodeInfo"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="mobileCode" type="s:string" /> <s:element minOccurs="0" maxOccurs="1" name="userID" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="getMobileCodeInfoResponse"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="getMobileCodeInfoResult" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="getDatabaseInfo"> <s:complexType /> </s:element> <s:element name="getDatabaseInfoResponse"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="getDatabaseInfoResult" type="tns:ArrayOfString" /> </s:sequence> </s:complexType> </s: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="string" nillable="true" type="s:string" /> <s:element name="ArrayOfString" nillable="true" type="tns:ArrayOfString" /> </s:schema> </wsdl:types> <wsdl:message name="getMobileCodeInfoSoapIn"> <wsdl:part name="parameters" element="tns:getMobileCodeInfo" /> </wsdl:message> <wsdl:message name="getMobileCodeInfoSoapOut"> <wsdl:part name="parameters" element="tns:getMobileCodeInfoResponse" /> </wsdl:message> <wsdl:message name="getDatabaseInfoSoapIn"> <wsdl:part name="parameters" element="tns:getDatabaseInfo" /> </wsdl:message> <wsdl:message name="getDatabaseInfoSoapOut"> <wsdl:part name="parameters" element="tns:getDatabaseInfoResponse" /> </wsdl:message> <wsdl:message name="getMobileCodeInfoHttpGetIn"> <wsdl:part name="mobileCode" type="s:string" /> <wsdl:part name="userID" type="s:string" /> </wsdl:message> <wsdl:message name="getMobileCodeInfoHttpGetOut"> <wsdl:part name="Body" element="tns:string" /> </wsdl:message> <wsdl:message name="getDatabaseInfoHttpGetIn" /> <wsdl:message name="getDatabaseInfoHttpGetOut"> <wsdl:part name="Body" element="tns:ArrayOfString" /> </wsdl:message> <wsdl:message name="getMobileCodeInfoHttpPostIn"> <wsdl:part name="mobileCode" type="s:string" /> <wsdl:part name="userID" type="s:string" /> </wsdl:message> <wsdl:message name="getMobileCodeInfoHttpPostOut"> <wsdl:part name="Body" element="tns:string" /> </wsdl:message> <wsdl:message name="getDatabaseInfoHttpPostIn" /> <wsdl:message name="getDatabaseInfoHttpPostOut"> <wsdl:part name="Body" element="tns:ArrayOfString" /> </wsdl:message> <wsdl:portType name="MobileCodeWSSoap"> <wsdl:operation name="getMobileCodeInfo"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地省份、地区和手机卡类型信息</h3><p>输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。</p><br /></wsdl:documentation> <wsdl:input message="tns:getMobileCodeInfoSoapIn" /> <wsdl:output message="tns:getMobileCodeInfoSoapOut" /> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地数据库信息</h3><p>输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。</p><br /></wsdl:documentation> <wsdl:input message="tns:getDatabaseInfoSoapIn" /> <wsdl:output message="tns:getDatabaseInfoSoapOut" /> </wsdl:operation> </wsdl:portType> <wsdl:portType name="MobileCodeWSHttpGet"> <wsdl:operation name="getMobileCodeInfo"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地省份、地区和手机卡类型信息</h3><p>输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。</p><br /></wsdl:documentation> <wsdl:input message="tns:getMobileCodeInfoHttpGetIn" /> <wsdl:output message="tns:getMobileCodeInfoHttpGetOut" /> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地数据库信息</h3><p>输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。</p><br /></wsdl:documentation> <wsdl:input message="tns:getDatabaseInfoHttpGetIn" /> <wsdl:output message="tns:getDatabaseInfoHttpGetOut" /> </wsdl:operation> </wsdl:portType> <wsdl:portType name="MobileCodeWSHttpPost"> <wsdl:operation name="getMobileCodeInfo"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地省份、地区和手机卡类型信息</h3><p>输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。</p><br /></wsdl:documentation> <wsdl:input message="tns:getMobileCodeInfoHttpPostIn" /> <wsdl:output message="tns:getMobileCodeInfoHttpPostOut" /> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"><br /><h3>获得国内手机号码归属地数据库信息</h3><p>输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。</p><br /></wsdl:documentation> <wsdl:input message="tns:getDatabaseInfoHttpPostIn" /> <wsdl:output message="tns:getDatabaseInfoHttpPostOut" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="MobileCodeWSSoap" type="tns:MobileCodeWSSoap"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="getMobileCodeInfo"> <soap:operation soapAction="http://WebXml.com.cn/getMobileCodeInfo" style="document" /> <wsdl:input> <soap:body use="literal" /> </wsdl:input> <wsdl:output> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <soap:operation soapAction="http://WebXml.com.cn/getDatabaseInfo" 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="MobileCodeWSSoap12" type="tns:MobileCodeWSSoap"> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="getMobileCodeInfo"> <soap12:operation soapAction="http://WebXml.com.cn/getMobileCodeInfo" style="document" /> <wsdl:input> <soap12:body use="literal" /> </wsdl:input> <wsdl:output> <soap12:body use="literal" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <soap12:operation soapAction="http://WebXml.com.cn/getDatabaseInfo" 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="MobileCodeWSHttpGet" type="tns:MobileCodeWSHttpGet"> <http:binding verb="GET" /> <wsdl:operation name="getMobileCodeInfo"> <http:operation location="/getMobileCodeInfo" /> <wsdl:input> <http:urlEncoded /> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <http:operation location="/getDatabaseInfo" /> <wsdl:input> <http:urlEncoded /> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:binding name="MobileCodeWSHttpPost" type="tns:MobileCodeWSHttpPost"> <http:binding verb="POST" /> <wsdl:operation name="getMobileCodeInfo"> <http:operation location="/getMobileCodeInfo" /> <wsdl:input> <mime:content type="application/x-www-form-urlencoded" /> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> <wsdl:operation name="getDatabaseInfo"> <http:operation location="/getDatabaseInfo" /> <wsdl:input> <mime:content type="application/x-www-form-urlencoded" /> </wsdl:input> <wsdl:output> <mime:mimeXml part="Body" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="MobileCodeWS"> <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>,提供最新的国内手机号码段归属地数据,每月更新。<br />使用本站 WEB 服务请注明或链接本站:<a href="http://www.webxml.com.cn/" target="_blank">http://www.webxml.com.cn/</a> 感谢大家的支持!<br />&nbsp;</wsdl:documentation> <wsdl:port name="MobileCodeWSSoap" binding="tns:MobileCodeWSSoap"> <soap:address location="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx" /> </wsdl:port> <wsdl:port name="MobileCodeWSSoap12" binding="tns:MobileCodeWSSoap12"> <soap12:address location="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx" /> </wsdl:port> <wsdl:port name="MobileCodeWSHttpGet" binding="tns:MobileCodeWSHttpGet"> <http:address location="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx" /> </wsdl:port> <wsdl:port name="MobileCodeWSHttpPost" binding="tns:MobileCodeWSHttpPost"> <http:address location="http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx" /> </wsdl:port> </wsdl:service> </wsdl:definitions>
其中,soap:address location=""说明了web服务所在的url地址,service name=""说明了web服务的实现类,operation name=""说明了实现类中公开的可以调用的方法。
二、发布一个简单的webservice并调用
1)发布webservice服务器端
package cn.itcast.webservices.test; import javax.jws.WebService; import javax.xml.ws.Endpoint; @WebService public class HelloService { /** * @param args */ public static void main(String[] args) { Endpoint.publish("http://192.168.152.128:6888/hello", new HelloService()); } public String sayHello(String name) { return name + ": hello!!!!"; } }
服务器端的代码比较简单,注解WebService把java类标记为实现webservice或者是将Java接口标记为webservice接口。Endpoint的publish方法,会将一个用@WebService注解的类绑定到一个特定地址上并发布为webservice。(publish方法执行的时候,会启动新的线程,在该线程上监听客户端的请求)
查看wsdl如下:
<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.6 in JDK 6. --><definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://test.webservices.itcast.cn/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://test.webservices.itcast.cn/" name="HelloServiceService"> <types> <xsd:schema> <xsd:import namespace="http://test.webservices.itcast.cn/" schemaLocation="http://192.168.152.128:6888/hello?xsd=1"></xsd:import> </xsd:schema> </types> <message name="sayHello"> <part name="parameters" element="tns:sayHello"></part> </message> <message name="sayHelloResponse"> <part name="parameters" element="tns:sayHelloResponse"></part> </message> <portType name="HelloService"> <operation name="sayHello"> <input message="tns:sayHello"></input> <output message="tns:sayHelloResponse"></output> </operation> </portType> <binding name="HelloServicePortBinding" type="tns:HelloService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding> <operation name="sayHello"> <soap:operation soapAction=""></soap:operation> <input> <soap:body use="literal"></soap:body> </input> <output> <soap:body use="literal"></soap:body> </output> </operation> </binding> <service name="HelloServiceService"> <port name="HelloServicePort" binding="tns:HelloServicePortBinding"> <soap:address location="http://192.168.152.128:6888/hello"></soap:address> </port> </service> </definitions>
2)生成客户端代码
wsimport -s . http://192.168.152.128:6888/hello?wsdl
生成代码目录如下:
3)测试调用
package cn.itcast.webservices.test; public class Client { public static void main(String[] args) { HelloServiceService hss = new HelloServiceService(); HelloService hs = hss.getHelloServicePort(); System.out.println(hs.sayHello("wsc")); } }
运行结果:
三、调用网络上的一个免费的web服务