天天看点

WebService深入浅出(转)

WebService深入浅出

什么是Webservice

W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计。Web Service服务通常被定义为一组模块化的API,它们可以通过网络进行调用,来执行远程系统的请求服务。
           
简单的说:WebService即Web服务,它是一种跨编程语言和跨操作系统平台的远程调用技术。
           
Web服务:基于HTTP和XML的技术,HTTP是互联网上应用最为广泛的一种网络协议,而XML是跨平台的基础。
跨编程语言和跨操作平台:就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然!跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。
远程调用:就是一台计算机a上的一个程序可以调用到另外一台计算机b上的一个对象的方法,譬如,银联提供给商场的pos刷卡系统,商场的POS机转账调用的转账方法的代码其实是跑在银行服务器上。再比如,amazon,天气预报系统,淘宝网,校内网,百度等把自己的系统服务以webservice服务的形式暴露出来,让第三方网站和程序可以调用这些服务功能,这样扩展了自己系统的市场占有率
           
web Service:有两大类:
一类:传统的webservice,大web service,相对复杂。
一类:轻量级的webservice
           

WebService三要素

WebService的三要素是:
    SOAP (Simple Object Access Protocol):简易对象访问协议,soap用来描述传递信息的格式。
    WSDL (WebServices Description Language):Web服务描述语言,用来描述如何访问具体的接口。
    UDDI (Universal Description Discovery and Integration):通用描述、发现及整合,用来管理、分发、查询webService。
           

原生态WebService客户端编写 

常见的手机归属地查询? 

http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl 

1.打开cmd,执行wsimport生成代码。

你不懂命令为什么能生成代码不要紧,记住就好!这是JDK/BIN目录下自带的
           
  • 1
WebService深入浅出(转)

2.如图所示,代码生成在D:\MyTest\webservice。会生成class和java文件。删除class文件 

WebService深入浅出(转)

3.开始编写查询手机号归属地客户端 

eclipse创建工程,将生成的代码copy到你自己想要的包下。记得修改package导包 

然后编写第一个WebService客户端接口

package com.ssm.remote.webservice.client;

import com.ssm.remote.webservice.MobileCodeWS;
import com.ssm.remote.webservice.MobileCodeWSSoap;

/**
 * 第一个WebService客户端演示
 * 根据手机号查询手机归属地
 * http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
 * @author dongyang
 * 
 *  WebService的三要素是:(面试)
 *     SOAP (Simple Object Access Protocol):简易对象访问协议,soap用来描述传递信息的格式。
 *     WSDL (WebServices Description Language):Web服务描述语言,用来描述如何访问具体的接口。
 *     UDDI (Universal Description Discovery and Integration):通用描述、发现及整合,用来管理、分发、查询webService。
 *
 */

public class PhoneAddressClient {

    public static void main(String[] args) {
        System.out.println(getPhoneAddress("15000814726"));
    }

    public static String getPhoneAddress(String phone){
        //1.实例化生成的服务类
        MobileCodeWS ws = new MobileCodeWS();
        //2.调用服务类的方法获取接口实例
        MobileCodeWSSoap soap = ws.getMobileCodeWSSoap();
        //3.通过接口直接获取数据
        return soap.getMobileCodeInfo(phone,"");
    }
}
           
WebService深入浅出(转)
这就是原生态的WebServiceke客户端接口。
简单熟悉这个例子之后。下面开始自定义服务端,发布服务,编写客户端
           

自定义WebService服务端并发布服务编写客户端测试 

1.编写服务接口

package com.ssm.remote.webservice.server;

/**
 * WebService服务端
 * @author dongyang
 *
 */
public interface FisrtWebService {

    String getAddressByPhoneNo(String phoneNo);
}
           

2.编写接口实现类

package com.ssm.remote.webservice.server.impl;

import javax.jws.WebService;

import com.ssm.remote.webservice.server.FisrtWebService;

@WebService//加上这个注解,表示此实现类就是WebService服务
public class FisrtWebServiceImpl implements FisrtWebService {

    public String getAddressByPhoneNo(String phoneNo) {
        return phoneNo + ": 归属地是上海";
    }

}
           

3.发布服务

package com.ssm.remote.webservice.server;

import javax.xml.ws.Endpoint;

import com.ssm.remote.webservice.server.impl.FisrtWebServiceImpl;

/**
 * 发布服务
 * @author dongyang
 *
 */
public class PublishServerTest {

    public static void main(String[] args) {
        //参数1:服务被访问的url   ip+端口号+服务名
        //参数2:实现类
        Endpoint.publish("http://localhost:9999/getAddress", new FisrtWebServiceImpl());
        System.out.println("服务发布成功");

        //查看WebService服务是否启动  url+?wsdl
        //http://localhost:9999/getAddress?wsdl是否能显示

    }
}
           

4.验证服务是否发布成功 

访问发布服务的ip+端口+服务名+?wsdl 

http://localhost:9999/getAddress?wsdl是否能显示 

WebService深入浅出(转)

5.照第一个例子那样通过命令生成代码,编写客户端代码。这里教大家生成代码自定义包名并将class文件和java文件分开 

WebService深入浅出(转)
类似于那种原生态的客户端,就不重复了,下面编写一个优化的客户端。
还是老样子,把生成的代码copy过来。

特别注意,客户端的FisrtWebServiceImpl是接口,不是服务端编写的实现类
           
package com.ssm.remote.webservice.client;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

/**
 * 自定义WebService服务端的客户端调用演示
 * @author dongyang
 *
 */
public class FisrtClinet {

    public static void main(String[] args) throws MalformedURLException {

        //TODO 也可以按照入门案例PhoneAddressClient那样调用,但是这样是不是更好呢?更具灵活性

        //FisrtWebServiceImplService是自动生成的接口,不是服务端的实现类
        Service service = Service.create(new URL("http://localhost:9999/getAddress?wsdl")
                , new QName("http://impl.server.webservice.remote.ssm.com/","FisrtWebServiceImplService"));
        FisrtWebServiceImpl impl = service.getPort(FisrtWebServiceImpl.class);
        System.out.println(impl.getAddressByPhoneNo("15000815726"));
    }

}
           
WebService深入浅出(转)

wsdl的基本结构 

举我们自定义的服务的wsdl:

<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://impl.server.webservice.remote.ssm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.server.webservice.remote.ssm.com/" name="FisrtWebServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://impl.server.webservice.remote.ssm.com/" schemaLocation="http://localhost:9999/getAddress?xsd=1"/>
</xsd:schema>
</types>
<message name="getAddressByPhoneNo">
<part name="parameters" element="tns:getAddressByPhoneNo"/>
</message>
<message name="getAddressByPhoneNoResponse">
<part name="parameters" element="tns:getAddressByPhoneNoResponse"/>
</message>
<portType name="FisrtWebServiceImpl">
<operation name="getAddressByPhoneNo">
<input wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoRequest" message="tns:getAddressByPhoneNo"/>
<output wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoResponse" message="tns:getAddressByPhoneNoResponse"/>
</operation>
</portType>
<binding name="FisrtWebServiceImplPortBinding" type="tns:FisrtWebServiceImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="getAddressByPhoneNo">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="FisrtWebServiceImplService">
<port name="FisrtWebServiceImplPort" binding="tns:FisrtWebServiceImplPortBinding">
<soap:address location="http://localhost:9999/getAddress"/>
</port>
</service>
</definitions>
           
WebService深入浅出(转)

离线解析

场景:你开发客户端的时候,不能和服务端网络连接。但程序还要开发,通过分析发现,客户端开发主要有wsdl的文档就可以了。因为有该文档,就可以生成桩(客户端代码)。
因此我们可以将wsdl保存下来,保存成xml。在不能访问服务端的情况下使用。
           
  • 1
  • 2
WebService深入浅出(转)
<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://impl.server.webservice.remote.ssm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://impl.server.webservice.remote.ssm.com/" name="FisrtWebServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://impl.server.webservice.remote.ssm.com/" schemaLocation="http://localhost:9999/getAddress?xsd=1"/>
</xsd:schema>
</types>
<message name="getAddressByPhoneNo">
<part name="parameters" element="tns:getAddressByPhoneNo"/>
</message>
<message name="getAddressByPhoneNoResponse">
<part name="parameters" element="tns:getAddressByPhoneNoResponse"/>
</message>
<portType name="FisrtWebServiceImpl">
<operation name="getAddressByPhoneNo">
<input wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoRequest" message="tns:getAddressByPhoneNo"/>
<output wsam:Action="http://impl.server.webservice.remote.ssm.com/FisrtWebServiceImpl/getAddressByPhoneNoResponse" message="tns:getAddressByPhoneNoResponse"/>
</operation>
</portType>
<binding name="FisrtWebServiceImplPortBinding" type="tns:FisrtWebServiceImpl">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="getAddressByPhoneNo">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="FisrtWebServiceImplService">
<port name="FisrtWebServiceImplPort" binding="tns:FisrtWebServiceImplPortBinding">
<soap:address location="http://localhost:9999/getAddress"/>
</port>
</service>
</definitions>
           

SOAP协议

SOAP,Simple Object Access Protocol,简单对象访问协议,简单的说就是用于访问网络服务的协议;它是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。

SOAP是一种网络通信协议,用于网络上、不同平台、不同语言的应用程序间的通讯。
WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议。SOAP提供了标准的RPC方法来调用Web Service。
  SOAP协议 = HTTP协议 + XML数据格式。
  SOAP协议定义了SOAP消息的格式,SOAP协议是基于HTTP协议的,SOAP也是基于XML和XSD的,XML是SOAP的数据编码方式。
SOAP很就简单并可扩展支持面向对象,允许跨防火墙。
SOAP被作为 W3C 标准来发展。
SOAP现行两个版本:1.1和1.2。
           

SOAP、HTTP、TCP/IP之间的关系 

WebService深入浅出(转)

SOAP协议分为1.1和1.2两个版本

为了兼容性,大部分程序员都会优先使用1.1
           

SOAP消息的标准格式 

WebService深入浅出(转)

SOAP1.1和SOAP1.2协议的异同

SOAP1.1和1.2版本之间的大部分差异通常也是可以忽略的
SOAP1.1只可以绑定到HTTP协议,而SOAP1.2除了HTTP协议之外还支持SMTP绑定。在JAX-WS中,类似于大多数框架,SOAP1.1作为默认实现,尽管如此在JAX-WS中可以随时采用SOAP1.2。
           
应用的价值:
1.  尽量使用同版本的来相互调用,原因,兼容性好,性能高。
2.  如果服务端使用1。1,那么客户端只能使用1。1,但服务端使用1。2,那么客户端可以使用1。1或1。2。,优先用1。2。但国内,很多客户端的开发为了适应不同版本的服务端,会用1。1来开发。
           

用jax-ws开发的客户端会自动适应服务端的版本。

性能压力测试

我们自己编写的服务端,肯定需要自己测试,行不行。性能如何?
博主推荐SoapUI5.2.1。当然你可以下载其余软件或者其余版本
           
WebService深入浅出(转)
WebService深入浅出(转)

CXF框架和Spring的集成开发包括hessian的开发请留意续集