实验目的:安装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/">&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;WebXml.com.cn&lt;/a&gt; &lt;strong&gt;国内手机号码归属地查询WEB服务&lt;/strong&gt;,提供最新的国内手机号码段归属地数据,每月更新。&lt;br /&gt;使用本站 WEB 服务请注明或链接本站:&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;http://www.webxml.com.cn/&lt;/a&gt; 感谢大家的支持!&lt;br /&gt;&amp;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/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地省份、地区和手机卡类型信息&lt;/h3&gt;&lt;p&gt;输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。&lt;/p&gt;&lt;br /&gt;</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/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地数据库信息&lt;/h3&gt;&lt;p&gt;输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。&lt;/p&gt;&lt;br /&gt;</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/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地省份、地区和手机卡类型信息&lt;/h3&gt;&lt;p&gt;输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。&lt;/p&gt;&lt;br /&gt;</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/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地数据库信息&lt;/h3&gt;&lt;p&gt;输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。&lt;/p&gt;&lt;br /&gt;</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/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地省份、地区和手机卡类型信息&lt;/h3&gt;&lt;p&gt;输入参数:mobileCode = 字符串(手机号码,最少前7位数字),userID = 字符串(商业用户ID) 免费用户为空字符串;返回数据:字符串(手机号码:省份 城市 手机卡类型)。&lt;/p&gt;&lt;br /&gt;</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/">&lt;br /&gt;&lt;h3&gt;获得国内手机号码归属地数据库信息&lt;/h3&gt;&lt;p&gt;输入参数:无;返回数据:一维字符串数组(省份 城市 记录数量)。&lt;/p&gt;&lt;br /&gt;</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/">&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;WebXml.com.cn&lt;/a&gt; &lt;strong&gt;国内手机号码归属地查询WEB服务&lt;/strong&gt;,提供最新的国内手机号码段归属地数据,每月更新。&lt;br /&gt;使用本站 WEB 服务请注明或链接本站:&lt;a href="http://www.webxml.com.cn/" target="_blank"&gt;http://www.webxml.com.cn/&lt;/a&gt; 感谢大家的支持!&lt;br /&gt;&amp;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>
View Code

其中,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服务