WebService初识

  Web service 是一种跨编程语言和跨操作系统平台的远程调用技术,即跨平台远程调用技术。也就是说,不管是J2EE架构,还是.net架构 只要按照规范就可以进行通信,实现数据交互等。

  这里说的"规范"是指,Webservice平台必须提供一种标准来描述Web service,让客户可以得到足够的信息来调用这个Web service。最后,我们还必须有一种方法来对这个Web service进行远程调用,这种方法实际上是一种远程过程调用协议(RPC)。Webservice 就是一种部署在网络上的API。

  RPC的全称为Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样。RPC 可以基于 HTTP 或 TCP 协议,Web Service 就是基于 HTTP 协议的 RPC,它具有良好的跨平台性,但其性能却不如基于 TCP 协议的 RPC。直接影响 RPC 性能的有两个方面,一是传输方式,二是序列化。
  实现RPC的协议有很多,比如最早的CORBA,Java RMI,以及现在用的Web Service,Hessian,Thrift,甚至Rest API等。
  因此,WebService可以理解为实现RPC的一种方式,传输数据格式为XML,采用SOAP协议,RPC的实现方式为SOAP RPC。  

  xml是webservice的跨平台的基础,XML主要的优点在于它既与平台无关,又与厂商无关。

  XSD,W3C为webservice制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何编程语言写的webservice接口在发送数据时都要转换成webservice标准的XSD发送。

  SOAP(Simple Object Access Protocol) 协议传输,soap属于w3c标准。Soap协议是基于http的应用层协议,soap协议传输的是xml数据。

  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 消息就是一个普通的 XML 文档,包含下列元素:
     必需的 Envelope 元素,可以把此 XML 文档标识为一条 SOAP 消息;
     可选的 Header 元素,包含头部信息;
     必需的 Body 元素,包含所有的调用和响应信息;
     可选的 Fault 元素,提供在处理此时所发生错误的有关信息。

 

<?xml version="1.0"?>
<soap:Envelope
 xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
 soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> 
<soap:Header>

</soap:Header> 
<soap:Body>

<soap:Fault>

</soap:Fault>
</soap:Body>
</soap:Envelope> 

 

  WSDL(Web Services Description Language)是一个基于XML的语言,用于描述Web Service及其函数、参数和返回值。它是WebService客户端和服务器端都能理解的标准格式。WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。

  采用wsdl作为描述语言即webservice使用说明书,wsdl属w3c标准。

  我们平时在生活中见过的一些便民生活网站就广泛地使用了webservice技术,诸如:

  在使用中,客户端与服务端的部署如下:

  客户端程序和服务端程序可以是部署在同一个计算机上的两个程序,但通常客户端和服务端是部署在不同的计算机上的。 

  客户端和服务端之间的网络必须连通,客户端和服务端之间使用网络协议进行通信。 

  服务端监听一个端口,客户端通过服务端监听的端口进行请求,客户端通过ip+端口去调用服务端,比如:tomcat启动起来监听8080端口,即tomcat对外提供服务,浏览器即客户端通过http协议访问tomcat8080端口。 

   客户端通过网络通信协议访问服务端,网络协议包括TCPUDP两大通信协议:  

  TCP是一种面向连接的协议,提供可靠的数据传输,一般服务质量要求比较高的情况,使用这个协议。TCP支持的应用协议主要有:Telnet、FTP、SMTP、HTTP等; 

  UDP---用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。UDP支持的应用层协议主要有:NFS(网络文件系统)、SNMP(简单网络管理协议)、DNS(主域名称系统)、TFTP(通用文件传输协议)等。 

  客户端/服务器模式早期主要应用于c/s应用,web兴起后主要应用于b/s应用,b/sc/s的好处就在于b/s是基于浏览器客户端访问服务端。

  webService存在三要素:

  1.soap

  SOAP即简单对象访问协议(Simple Object Access Protocal) 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息,简单理解为soap=http+xml。Soap协议版本主要使用soap1.1、soap1.2。
  SOAP不是webservice的专有协议,其他应用协议也使用soap传输数据。例如,SMTP、tr069等。

  2.wsdl

  WSDL 是基于 XML 的用于描述Web Service及其函数、参数和返回值。通俗理解Wsdl是webservice的使用说明书。 

  3.UDDI 

  UDDI (Universal Description, Discovery and Integration,通用描述、发现与集成服务)是一种目录服务,通过它,企业可以使用它对 Web services 进行注册和搜索企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册的web service服务,从而达到资源共享。 UDDI旨在将全球的webservcie资源进行共享,促进全球经济合作。

  目前大部分企业使用webservice并不是必须使用UDDI,因为用户通过WSDL知道了web service的地址,可以直接通过WSDL调用webservice 

  接下来,我通过编码实现一个自定义的webservice服务端。

package com.itszt.weather;

import java.util.List;

/**
 * 1.编写SEI(Service Endpoint Interface),
 * SEI在webservice中称为portType,在java中称为接口。
 * 气温查询接口
 */
public interface WeatherQuery {
    //1.查询当前的气温
    public String queryNowTem();
    //2.查询某个城市未来两天的气温
    public List<String> query2Days();
}
------------------------------------------------------------
package com.itszt.weather;
import javax.jws.WebService;
import java.util.ArrayList;
import java.util.List;
/**
 * 2.编写SEI实现类,此类作为webservice提供服务的类
 * 气温查询实现类
 * 注意:SEI实现类中至少要有一个非静态的公开方法作为webservice的服务方法。
 * public class 上边要加上@WebService 
 */
@WebService
public class WeatherQueryImpl implements WeatherQuery{
    @Override
    public String queryNowTem() {
        System.out.println("外部系统访问到了--->WeatherQueryImpl.queryNowTem");
        return "45度";
    }

    @Override
    public List<String> query2Days() {
        System.out.println("外部系统访问到了--->WeatherQueryImpl.query2Days");
        List<String> days=new ArrayList<>();
        days.add("晴天");
        days.add("阴天");
        return days;
    }
}
----------------------------------------------------
package com.itszt.weather;
import javax.xml.ws.Endpoint;
/**
 * 3.endpoint发布服务
 */
public class Main {
    public static void main(String[] args) {
        //发布我们设计的天气预报
        Endpoint.publish("http://192.168.1.6:10086/SzWeather",
                new WeatherQueryImpl());
    }
}

  Webservice发布成功后,通过wsdl查看webservice发布的正确性。 

http://192.168.1.6:10086/SzWeather?wsdl

   

   需要注意的是:Wsdl不是webService,只是获取一个用于描述WebService的说明文件;wsdl- -WebService Description Language,是以XML文件形式来描述WebService的”说明书”,有了说明书,我们才可以知道如何使用或是调用这个服务。

  接下来,我们通过Wsimport生成客户端调用webservice类。

  wsimportjdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码)。当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码,服务端通过客户端代码调用webservice

   先确定生成webservice客户端代码的路径:

    在DOS中生成客户端代码的命令: 

wsimport -s E:\webService\gen\source -d E:\webService\gen\classes http://192.168.1.6:10086/SzWeather?wsdl

  

  生成weather.jar包:

  接下来,建一个客户端工程调用服务端提供的webservice服务。其中,将生成的weather.jar添加到客户端工程中作为依赖。

    

package weatherClient;
import com.itszt.weather.WeatherQueryImpl;
import com.itszt.weather.WeatherQueryImplService;
import java.util.List;
/**
 * 客户端测试类,调用服务端提供的服务
 */
public class ClientTest {
    public static void main(String[] args) {
        //创建服务视图
        WeatherQueryImplService weatherService=new WeatherQueryImplService();
        //根据服务视图得到服务端点
        WeatherQueryImpl weatherQueryImpl = weatherService.getPort(WeatherQueryImpl.class);
        //调用WeatherQueryImpl的服务方法
        String nowInfo = weatherQueryImpl.queryNowTem();
        List<String> query2Days = weatherQueryImpl.query2Days();
        System.out.println(nowInfo);
        System.out.println(query2Days);
    }
}

   客户端控制台打印如下:

45度
[晴天, 阴天]

  服务端控制台打印如下:

外部系统访问到了--->WeatherQueryImpl.queryNowTem
外部系统访问到了--->WeatherQueryImpl.query2Days

  说明客户端成功地访问到了服务端提供的天气信息服务。

  另外,我们还可以通过webservice的注解修改wsdl中的信息。

package com.itszt.weather;
import java.util.List;
/**
 * 1.编写SEI(Service Endpoint Interface),
 * SEI在webservice中称为portType,在java中称为接口。
 * 气温查询接口
 */
public interface WeatherQuery {
    //1.查询当前的气温[修改参数信息]
    public String queryNowTem(String city,String date);
    //2.查询某个城市未来两天的气温
    public List<String> query2Days();
}
--------------------------------------------------
package com.itszt.weather;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import java.util.ArrayList;
import java.util.List;
/**
 * 2.编写SEI实现类,此类作为webservice提供服务的类
 * 气温查询实现类
 * 注意:SEI实现类中至少要有一个非静态的公开方法作为webservice的服务方法。
 * public class 上边要加上@WebService
 * [修改服务名称,端口名称]
 */
@WebService(serviceName = "SzService",portName = "hello")
public class WeatherQueryImpl implements WeatherQuery{
    //修改方法名称
    @Override
    @WebMethod(operationName = "queryTem")
    public String queryNowTem(@WebParam(name = "城市名称") String city,@WebParam(name = "日期") String date) {
        System.out.println("city = [" + city + "], date = [" + date + "]");
        System.out.println("外部系统访问到了--->WeatherQueryImpl.queryNowTem");
        return city+"的"+date+"气温是:45度";
    }

    @Override
    @WebMethod(operationName = "query2Days")
    public List<String> query2Days() {
        System.out.println("外部系统访问到了--->WeatherQueryImpl.query2Days");
        List<String> days=new ArrayList<>();
        days.add("晴天");
        days.add("阴天");
        return days;
    }
}
-------------------------------------------------
package com.itszt.weather;
import javax.xml.ws.Endpoint;
/**
 * 3.endpoint发布服务
 */
public class Main {
    public static void main(String[] args) {
        //发布我们设计的天气预报
        Endpoint.publish("http://192.168.1.150:10086/SzWeather",
                new WeatherQueryImpl());
    }
}

  运行上述代码,并重新在浏览器中打开wsdl使用说明书,并生成jar包。为简化操作,创建一个gen.bat的批处理文件,其中的命令如下:

wsimport -s E:\webService\gen\source -d E:\webService\gen\classes http://192.168.1.150:10086/SzWeather?wsdl

e:

cd E:\webService\gen\classes

jar cvf weather4.jar com

  创建访问webservice的客户端:

package weatherClient;
import com.itszt.weather.WeatherQueryImpl;
import com.itszt.weather.SzService;
import java.util.List;
/**
 * 客户端测试类,调用服务端提供的服务
 */
public class ClientTest {
    public static void main(String[] args) {
        //创建服务视图
        SzService weatherService=new SzService();
        //根据服务视图得到服务端点
        WeatherQueryImpl weatherQueryImpl = weatherService.getPort(WeatherQueryImpl.class);
        //调用WeatherQueryImpl的服务方法
        String nowInfo = weatherQueryImpl.queryTem("北京","10月10日");
        List<String> query2Days = weatherQueryImpl.query2Days();
        System.out.println(nowInfo);
        System.out.println(query2Days);
    }
}

  客户端执行后控制台显示如下:

北京的10月10日气温是:45度
[晴天, 阴天]

  服务器端的控制台执行如下:

city = [北京], date = [10月10日]
外部系统访问到了--->WeatherQueryImpl.queryNowTem
外部系统访问到了--->WeatherQueryImpl.query2Days  

  综上所述,webservice的优点有:

  (1)采用xml支持跨平台远程调用。

  (2)基于http的soap协议,可跨越防火墙。
  (3)支持面向对象开发。
  (4)有利于软件和数据重用,实现松耦合。 

  同时,webservice也有这样的缺点:由于soap是基于xml传输,本身使用xml传输会传输一些无关的东西从而降低效率不高,随着soap协议的完善,soap协议增加了许多内容,这样就导致了使用soap协议进行数据传输的效率不高。 

  总的来说,从宏观上讲,webservice可用于软件集成和复用。

  从微观上来说,webservice适用场景有:

  (1)用于接口服务。如果不考虑客户端类型,不考虑性能,建议使用:

  a.用于公开接口服务。面向互联网公开的接口,例如:某公司产品促销介绍、股票信息查询等,因为webservice使用的soap协议是一个标准协议,其它公司使用标准协议通信,方便系统开发和维护。再比如:便民网站的天气查询接口、火车时刻查询接口等。

  b.用于内部接口服务。一个大的系统平台是由若干个系统组成,系统与系统之间存在数据访问需求,为了减少系统与系统之间的耦合性可以将接口抽取出来提供单独的接口服务供其它系统调用。

  c.服务端已经确定使用webservice,客户端无法选择,只能使用webservice。 

  不适用webservice的场景有:

  a.性能要求很高的应用,不建议使用webservice.比如银行交易系统、股票交易系统等,任何延迟都可能造成无法估量的损失。 

  b.同构程序之间通信不建议使用webservice。比如,Java中RMI(Remote Method Invocation,远程方法调用,指能够让在某个java虚拟机上的对象像调用本地对象一样调用另一个java 虚拟机中的对象上的方法),同样可以实现远程调用,而且性能比webservice好很多

posted @ 2018-04-03 22:52  奔跑在梦想的道路上  阅读(324)  评论(0编辑  收藏  举报