webservice

来源:互联网 发布:怎么淘宝介入 编辑:程序博客网 时间:2024/05/20 12:48

     前面大致将了一些cxf实现webservice服务,此次对webservice作一个更为详细的总结.

     webservice的应用场景:

 1.用户公共接口的接口服务.

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

2.用户内部接口服务.

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


       webservice能够优点:

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

2、基于http的soap协议,可跨越防火墙。

3、支持面向对象开发。

4、有利于软件和数据重用,实现松耦合。

       webservice缺点

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

         Webservice简介

  • Web service 即web服务,它是一种跨编程语言和跨操作系统平台的远程调用技术即跨平台远程调用技术。
  • 采用标准SOAP(Simple Object Access Protocol)  协议传输,soap属于w3c标准。Soap协议是基于http的应用层协议,soap协议传输是xml数据。采用wsdl作为描述语言即webservice使用说明书,wsdl属w3c标准。
  • xml是webservice的跨平台的基础,XML主要的优点在于它既与平台无关,又与厂商无关。
  • XSD,W3C为webservice制定了一套传输数据类型,使用xml进行描述,即XSD(XML Schema Datatypes),任何编程语言写的webservice接口在发送数据时都要转换成webservice标准的XSD发送。
  • 当前非SOAP协议的webService以轻量为首要目标,比如http rest方式也是webservice的一种方式,或者直接使用http自定义数据协议,比如http传输json数据,http传输xml数据等。

       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及其函数、参数和返回值。通俗理解Wsdlwebservice的使用说明书。

          3.uddi

        UDDI 是一种目录服务,通过它,企业可注册并搜索 Web services。企业将自己提供的Web Service注册在UDDI,也可以使用别的企业在UDDI注册的web service服务,从而达到资源共享。 UDDI旨在将全球的webservcie资源进行共享,促进全球经济合作。

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

     Webservice开发规范

       JAVA 中共有三种WebService 规范,分别是JAX-WS(JAX-RPC)、JAXM&SAAJ、JAX-RS。

       1.JAX-WS

        JAX-WS  的全称为 Java API for XML-Based Webservices,早期的基于SOAPJAVAWeb服务规范JAX-RPCJava API For XML-Remote Procedure Call)目前已经被JAX-WS规范取代。从java5开始支持JAX-WS2.0版本,Jdk1.6.0_13以后的版本支持2.1版本,jdk1.7支持2.2版本。

      2.AXM&SAAJ

       JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的API,SAAJ(SOAP With Attachment API For Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输等,JAXM&SAAJ 与JAX-WS 都是基于SOAP 的Web 服务,相比之下JAXM&SAAJ 暴漏了SOAP更多的底层细节,编码比较麻烦,而JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心SOAP 的任何细节.

      3.JAX-RS

    JAX-RS JAVA针对REST(Representation StateTransfer)风格制定的一套Web服务规范,由于推出的较晚,该规范(JSR 311,目前JAX-RS的版本为1.0)并未随JDK1.6一起发行。

     Webservice与Socket(Socket与Webservice的区别、TCP/IP协议、HTTP协议)

       

     

        Webservice采用soap协议进行通信,底层基于socket通信,webservice不需专门针对数据流的发送和接收进行处理,是一种跨平台的面向对象远程调用技术。

  • Socket  是基于TCP/ip的传输层协议
  • Webservice是基于http协议传输数据,http是基于tcp的应用层协议
  • Webservice采用了基于httpsoap协议传输数据。
  • Socket接口通过操作流编程传输数据,不支持面向对象。
  • Webservice 接口支持面向对象,最终webservice将对象进行序列化后通过流传输
   Socket优点:
  • Socket采用tcp、udp底层协议通信,传输速度快,适用于传输大数量的数据。
  • socket具有平台无关性,java写的socket的客户端可以访问c写的socket服务端。
   Socket缺点

  接口传输的数据需要手动解析,socket通信的接口协议需要自定义,比如:自定义一种字符串拼接的格式,比如自定义的xml数据,自定义麻烦之处在接口调用方和接口服务端需要互相讨论确定接口的协议内容,不方便,好处:适用于传输大数量的数据。



      webservice技术拓展

        虽然java中定义webservice开发规范采用soap协议,但由于soap协议本身的缺点现在更多的webservice接口则直接采用http+自定义协议通信,比如http传输json串、http传输自定义格式的数据,因为这样做比soap协议更快捷,例如某些第三方支付公司的支持接口就直接采用http原始协议通信、http rest方式通信。

        webservice即web服务,只要这个计算机在互联网内,它对外提供的服务接口都可以认为是一个webservice,除了使用http、soap进行通信外如果要保证性能可以直接使用tcp,比如采用socket方式,但是socket方式需要手动通过流编程解析数据,有些麻烦,如果有保证传输速度及跨平台的前提下基于面向对象开发服务接口及客户端程序的技术最好不过,hessian框架就可以保证传输速度及在跨平台的前提下基于面向对象开发远程调用接口。

        总结:webservice可以实现的技术有好多,socket、http、soap方式、hessian等,在实际应用时根据具体的需求和场景去选择应用技术。

      webservice技术选型

          1. 协议约定

         你作为客户端要调用别人的接口,对方服务接口用的是什么协议客户端一般也用什么协议,比如服务端采用socket,客户端使用socket方式通信,服务端使用对外提供soap方式的webservice,客户端使用soap协议与服务端通信。

          2. 通用性

         对于一个webservice主要考虑接口的通用性时,在不要求性能的前提下可以使用soap协议。

如果要考虑接口的通用性还要考虑接口的性能可以采用http+自定义协议,比如http+json串,因为http本身就是web应用中的基础协议,json格式的数据也成为当前web开发中流行数据格式。

         3.高性能

         对于一个webservice主要作为内部系统之间通信使用,比如:联通、移动公司内部的若干系统之间进行数据传输,这类接口主要考虑的是性能,可以直接采用socket通信、hessian等,几种技术性能从高到低是:socket>hessian>http>soap。

        4.开发规范

        当然要注意,有些正规的公司会制定自己公司的开发规范,比如内部系统接口统一采用hessian,统一采用http,并不总是使用性能最高的方式,因为公司会综合考虑自己的人力资源情况在有限的成本下使用最合适的技术才是公司在进行技术选型时所遵循的原则。

      webservice 与http关系

     http与webservice之间的关系,可以用一句话描述:Webservice采用了基于http的soap协议传输数据。
      webservice的三要素soap,wsdl,uddi并未涉及网络通信(soap协议与http通信协议是有本质区别的),soap只是应用协议,并非通信协议,它所依赖的下层通信方式不单单是HTTP,也有SOAP over SMTP, SOAP over TCP,由于HTTP协议群众基础广,开发调试方便,所以,成了WebService中最为流行的方式(HTTP也是TCP上性能比较差的协议,因为HTTP是基于TCP的,有3次握手,再加上HTTP是个文本传输协议(虽然也可以传二进制的附件,但业务逻辑还是文本用的多),又有很多复杂的HEADER。所以人们发明了一些更高效的通信协议来做远程调用,比如ACE、ICE、Corba、淘宝的HSF)。
        http协议传输的都是字符串了,webservice则是包装成了更复杂的对象.webservice就是使用soap协议得到你想要的东西,相比httpservice能处理些更加复杂的数据类型.
        soap基于http通信(见下文soap),发送的就是一个post的http请求,请求内容格式text/xml(soap1.2是application/soap+xml),返回text/xml.webservice接受xml格式的请求进行解析,印射到相应的server方法中进行出处理.用jdk的wsimport或者cxf的wsdl2java生产的客户端,其主要的代码就是将请求封装成xml,解析返回的xml数据.(reference)
        jaxws是一个标准的webservice服务,jaxrs一些get或者post更像是httpservice(post中soap的xml请求更像webservice)
       webservice Examples

1.jax-ws

      jaxws注解的作用主要是用来规范webservice的接口,使用注解可以指定服务名称、portType名称、接口参数名称等。

     WebService的注解都位于javax.jws包下:

    @WebService-定义服务,在public class上边

  • targetNamespace:指定命名空间
  • name:portType的名称
  • portName:port的名称
  • serviceName:服务名称
  • endpointInterface:SEI接口地址,如果一个服务类实现了多个接口,只需要发布一个接口的方法,可通过此注解指定要发布服务的接口。

       @WebMethod-定义方法,在公开方法上边

  • operationName:方法名
  • exclude:设置为true表示此方法不是webservice方法,反之则表示webservice方法

       @WebResult-定义返回值,在方法返回值前边

  • name:返回结果值的名称

       @WebParam-定义参数,在方法参数前边

  • name:指定参数的名称

作用:

         通过注解,可以更加形像的描述Web服务。对自动生成的wsdl文档进行修改,为使用者提供一个更加清晰的wsdl文档。

当修改了WebService注解之后,会影响客户端生成的代码。调用的方法名和参数名也发生了变化

注意事项

      @WebMethod对所有非静态的公共方法对外暴露为服务.

  • 对于静态方法或非public方法是不可以使用@WebMethod注解的.
  • 对public方法可以使用@WebMethod(exclude=true)定义为非对外暴露的服务。

       如果修改webservice的接口内容,比如namespaceportType,必须要重新生成客户端调用代码。

 服务端(新建jar项目)

sei

package service;/*编写SEI(Service Endpoint Interface),SEI在webservice中称为portType,在java中称为接口*/public interface WeatherInterface {//根据城市名称查询天气信息public String queryWeather(String cityName)throws Exception;}
sei impl

package service;import javax.jws.WebService;//@WebService标识此类可以发布为webservice服务@WebServicepublic class WeatherInterfaceImpl implements WeatherInterface {//如果此方法被调用执行说明客户端请求天气查询@Overridepublic String queryWeather(String cityName) throws Exception {System.out.println("from client..."+cityName);//查询天气 //使用静态数据表示查询天气结果//...//天气查询结果String result="晴";//如果方法返回值,说明服务端向客户端响应查询结果return result;}}
server

package service;import javax.xml.ws.Endpoint;public class WeatherServer {public static void main(String[] args) {//发布天气查询服务//第一个参数:服务地址//第二个参数:提供的java对象,实现SEI的实现类对象Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherInterfaceImpl());}}

访问http://127.0.0.1:12345/weather?wsdl 返回

This XML file does not appear to have any style information associated with it. The document tree is shown below.<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --><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://service/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://service/" name="WeatherInterfaceImplService"><types><xsd:schema><xsd:import namespace="http://service/" schemaLocation="http://127.0.0.1:12345/weather?xsd=1"/></xsd:schema></types><message name="queryWeather"><part name="parameters" element="tns:queryWeather"/></message><message name="queryWeatherResponse"><part name="parameters" element="tns:queryWeatherResponse"/></message><message name="Exception"><part name="fault" element="tns:Exception"/></message><portType name="WeatherInterfaceImpl"><operation name="queryWeather"><input wsam:Action="http://service/WeatherInterfaceImpl/queryWeatherRequest" message="tns:queryWeather"/><output wsam:Action="http://service/WeatherInterfaceImpl/queryWeatherResponse" message="tns:queryWeatherResponse"/><fault message="tns:Exception" name="Exception" wsam:Action="http://service/WeatherInterfaceImpl/queryWeather/Fault/Exception"/></operation></portType><binding name="WeatherInterfaceImplPortBinding" type="tns:WeatherInterfaceImpl"><soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="queryWeather"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output><fault name="Exception"><soap:fault name="Exception" use="literal"/></fault></operation></binding><service name="WeatherInterfaceImplService"><port name="WeatherInterfaceImplPort" binding="tns:WeatherInterfaceImplPortBinding"><soap:address location="http://127.0.0.1:12345/weather"/></port></service></definitions>
       解析wsdl

      简述wsdl

  • WSDL 指网络服务描述语言(Web Services Description Language)。
  • WSDL是一种使用 XML 编写的文档。这种文档可描述某个 Web service。它可规定服务的位置,以及此服务提供的操作(或方法)。
  • WSDL 是一种 XML 文档
  • WSDL 用于描述网络服务
  • WSDL 也可用于定位网络服务
        wsdl结构

<service>    服务视图,webservice的服务结点,它包括了服务端点

<binding>     为每个服务端点定义消息格式和协议细节

<portType>   服务端点,描述 web service可被执行的操作方法,以及相关的消息,通过binding指向portType

<message>   定义一个操作(方法)的数据参数(可有多个参数)

<types>        定义 web service 使用的全部数据类型

       建议阅读习惯:从下往上读先找到服务视图,通过binging找到protType,找到了protType就找到了我们要调用的webservice方法。

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

       wsimport.exe位于JAVA_HOME\bin目录下.

       常用参数为:

-d<目录>  - 将生成.class文件。默认参数。

-s<目录> - 将生成.java文件。

-p<生成的新包名> -将生成的类,放于指定的包下。

(wsdlurl) - http://server:port/service?wsdl,必须的参数。

        示例:

C:/> wsimport –s . http://127.0.0.1:1234/weather?wsdl

注意:-s不能分开,-s后面有个小点

运行后会在指定目录下(如上述命令就是c盘下)生成一大坨代码,新建一个client客户端jar(客户端一般和服务端是分开的),复制生成的代码





编写WeatherClient

package service;import service.Exception_Exception;import service.WeatherInterfaceImpl;import service.WeatherInterfaceImplService;public class WeatherClient {public static void main(String[] args) throws Exception_Exception {// 使用生成的调用代码创建代理对象,代理对象就是portType的代理对象,代理对象内部最终发起socket请求// 创建一个服务视图的对象WeatherInterfaceImplService weatherInterfaceImplService = new WeatherInterfaceImplService();// 通过服务视图创建portType的代理对象WeatherInterfaceImpl weatherInterfaceImplPort = weatherInterfaceImplService.getWeatherInterfaceImplPort();// 调用portType的方法String resultString = weatherInterfaceImplPort.queryWeather("北京");System.out.println("天气查询结果:" + resultString);}}
       运行client,结果----天气查询结果:晴

       查看上面的生成的代码中,访问通过"http://127.0.0.1:12345/weather?wsdl"获取wsdl(xml结构),根据其说明去访问相应的接口,返回值有诸多注解都带xml,也就是说返回也是xml, 也就验证了上面的基于xml的数据传输.值得一提的是,此处不同于jaxrs,jaxrs进行了rest风格的印射,是可以通过url(或http请求)直接访问

2.调用公网查询天气预报

      天气预报公网http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

      直接使用wsimport -s . url会报s:schema出错(jaxb不支持),需要将wsdl下载下来(另存为C:\Users\admin\Desktop\temp\WeatherWebService.xml)进行更改

      <s:element ref="s:schema" /><s:any />改成 <s:any minOccurs="2" maxOccurs="2"/>,一共有三处需要修改,建议查找<s:element ref="s:schema" />,修改时把<s:any />也要删掉,执行cmd进入C:\Users\admin\Desktop\temp\,执行wsimport -s . WeatherWebService.xml,将生产代码拷入新建的jar中

新建client访问

package cn.com.webxml;import java.io.IOException;import java.net.MalformedURLException;import java.net.URL;import java.util.List;import javax.xml.namespace.QName;import javax.xml.ws.Service;import cn.com.webxml.ArrayOfString;import cn.com.webxml.WeatherWebService;import cn.com.webxml.WeatherWebServiceSoap;public class WeatherClient {public static void main(String[] args) throws IOException { //######################通过Wsimport访问####################// 创建服务视图对象WeatherWebService weatherWebService = new WeatherWebService();// 通过服务视图对象创建portType的代理对象WeatherWebServiceSoap weatherWebServiceSoap = weatherWebService.getWeatherWebServiceSoap();//调用portType的方法ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("北京");//遍历公网天气查询服务返回的类型for(String message:arrayOfString.getString()){System.out.println(message);} //######################通过service访问####################/*//定义url,参数为wsdl地址URL url = new URL("file:/C:/Users/admin/Desktop/temp/WeatherWebService.xml");//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名QName qName = new QName("http://WebXml.com.cn/", "WeatherWebService");//创建服务视图Service service = Service.create(url, qName);//通过服务视图得到服务端点WeatherWebServiceSoap weatherWebServiceSoap =service.getPort(WeatherWebServiceSoap.class);//调用webserviceArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("郑州");List<String> resultlist = arrayOfString.getString();//查询天气查询结果for(String result:resultlist){System.out.println(result);}*//*######################通过service访问与通过Wsimport访问的区别####################Wsimport生成代码调用webservice无法指定webservice的地址,使用生成的服务视图类获取服务端点(postType)实例。Service调用Webservice可以指定webservice的地址,只需要服务端点的接口即可获取服务端点实例。*/}}
运行ok.

3.soap协议

1.soap协议(1.1版本)

     使用TCP/IP Monitor可以监视tcp/ip协议的报文内容,由于http是基于Tcp的应用协议,而webservice是基于http实现,所以通过tcp/ip monitor可以监视webservice请求及响应的内容。以案例1为例.

      eclipse设置tcp/ip monitor

     

     tcp/ip monitor监控的基本原理就是通过端口转发(上述12345就是目的端口,999是转发端口).

     启动客户端访问

URL url = new URL("http://127.0.0.1:999/weather?wsdl");//定义qname,第一个参数是命名空间,第二个参数名称是wsdl里边的服务名QName qName = new QName("http://service/", "WeatherInterfaceImplService");//创建服务视图Service service = Service.create(url, qName);//通过服务视图得到服务端点WeatherInterfaceImpl weatherInterfaceImpl =service.getPort(WeatherInterfaceImpl.class);//调用webserviceSystem.out.println(weatherInterfaceImpl.queryWeather("郑州"));

request监控

GET /weather?wsdl HTTP/1.1User-Agent: Java/1.7.0_72Host: 127.0.0.1:999Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2Connection: keep-alive###########以上是转发,以下是监控内容###############POST /weather HTTP/1.1Accept: text/xml, multipart/relatedContent-Type: text/xml; charset=utf-8SOAPAction: "http://service/WeatherInterfaceImpl/queryWeatherRequest"User-Agent: JAX-WS RI 2.2.4-b01Host: 127.0.0.1:999Connection: keep-aliveContent-Length: 200<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:queryWeather xmlns:ns2="http://service/"><arg0>郑州</arg0></ns2:queryWeather></S:Body></S:Envelope>
response

HTTP/1.1 200 OKTransfer-encoding: chunkedContent-type: text/xml;charset=utf-8Date: Mon, 31 Jul 2017 11:14:33 GMT8cc<?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.2.4-b01. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.4-b01. --><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://service/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://service/" name="WeatherInterfaceImplService"><types><xsd:schema><xsd:import namespace="http://service/" schemaLocation="http://127.0.0.1:999/weather?xsd=1"/></xsd:schema></types><message name="queryWeather"><part name="parameters" element="tns:queryWeather"/></message><message name="queryWeatherResponse"><part name="parameters" element="tns:queryWeatherResponse"/></message><message name="Exception"><part name="fault" element="tns:Exception"/></message><portType name="WeatherInterfaceImpl"><operation name="queryWeather"><input wsam:Action="http://service/WeatherInterfaceImpl/queryWeatherRequest" message="tns:queryWeather"/><output wsam:Action="http://service/WeatherInterfaceImpl/queryWeatherResponse" message="tns:queryWeatherResponse"/><fault message="tns:Exception" name="Exception" wsam:Action="http://service/WeatherInterfaceImpl/queryWeather/Fault/Exception"/></operation></portType><binding name="WeatherInterfaceImplPortBinding" type="tns:WeatherInterfaceImpl"><soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="queryWeather"><soap:operation soapAction=""/><input><soap:body use="literal"/></input><output><soap:body use="literal"/></output><fault name="Exception"><soap:fault name="Exception" use="literal"/></fault></operation></binding><service name="WeatherInterfaceImplService"><port name="WeatherInterfaceImplPort" binding="tns:WeatherInterfaceImplPortBinding"><soap:address location="http://127.0.0.1:999/weather"/></port></service></definitions>0HTTP/1.1 200 OKTransfer-encoding: chunkedContent-type: text/xml; charset=utf-8Date: Mon, 31 Jul 2017 11:14:33 GMT6e<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body>7b<ns2:queryWeatherResponse xmlns:ns2="http://service/"><return>晴 </return></ns2:queryWeatherResponse></S:Body></S:Envelope>0
     可以看出request与reponse 的content-type都是text/xml

     soap协议包含的元素

  • 必需有 Envelope 元素,此元素将整个 XML文档标识为一条SOAP消息
  • 可选的 Header 元素,包含头部信息
  • 必需有Body 元素,包含所有的调用和响应信息
  • 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息
  soap消息基本结构

<?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>

soap协议(1.2版本)

  Jaxws实现soap1.2需要加入jaxws扩展包,从sun下载jaxws-ri-2.2.8,解压jaxws-ri-2.2.8并将lib下的jar包加载到java工程中。

  在SEI实现类上添加如下注解@BindingType(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)

request

GET /weather?wsdl HTTP/1.1User-Agent: Java/1.7.0_72Host: 127.0.0.1:999Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2Connection: keep-alivePOST /weather HTTP/1.1Accept: application/soap+xml, multipart/relatedContent-Type: application/soap+xml; charset=utf-8;action="http://service/WeatherInterfaceImpl/queryWeatherRequest"User-Agent: JAX-WS RI 2.2.4-b01Host: 127.0.0.1:999Connection: keep-aliveContent-Length: 198<?xml version="1.0" ?><S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"><S:Body><ns2:queryWeather xmlns:ns2="http://service/"><arg0>郑州</arg0></ns2:queryWeather></S:Body></S:Envelope>
response

HTTP/1.1 200 OKTransfer-encoding: chunkedContent-type: text/xml;charset=utf-8Date: Mon, 31 Jul 2017 11:49:32 GMT8d8<?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.2.8 svn-revision#13980. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. --><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:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://service/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://service/" name="WeatherInterfaceImplService"><types><xsd:schema><xsd:import namespace="http://service/" schemaLocation="http://127.0.0.1:999/weather?xsd=1"/></xsd:schema></types><message name="queryWeather"><part name="parameters" element="tns:queryWeather"/></message><message name="queryWeatherResponse"><part name="parameters" element="tns:queryWeatherResponse"/></message><message name="Exception"><part name="fault" element="tns:Exception"/></message><portType name="WeatherInterfaceImpl"><operation name="queryWeather"><input wsam:Action="http://service/WeatherInterfaceImpl/queryWeatherRequest" message="tns:queryWeather"/><output wsam:Action="http://service/WeatherInterfaceImpl/queryWeatherResponse" message="tns:queryWeatherResponse"/><fault message="tns:Exception" name="Exception" wsam:Action="http://service/WeatherInterfaceImpl/queryWeather/Fault/Exception"/></operation></portType><binding name="WeatherInterfaceImplPortBinding" type="tns:WeatherInterfaceImpl"><soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/><operation name="queryWeather"><input><soap12:body use="literal"/></input><output><soap12:body use="literal"/></output><fault name="Exception"><soap12:fault name="Exception" use="literal"/></fault></operation></binding><service name="WeatherInterfaceImplService"><port name="WeatherInterfaceImplPort" binding="tns:WeatherInterfaceImplPortBinding"><soap12:address location="http://127.0.0.1:999/weather"/></port></service></definitions>0HTTP/1.1 200 OKTransfer-encoding: chunkedContent-type: application/soap+xml; charset=utf-8Date: Mon, 31 Jul 2017 11:49:32 GMT6c<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope"><S:Body>7b<ns2:queryWeatherResponse xmlns:ns2="http://service/"><return>晴 </return></ns2:queryWeatherResponse></S:Body></S:Envelope>0

soap1.1与1.2的比较

     相同之处:

  • soap1.1和soap1.2都是使用post方法
  • 都包括Envelope和body

 

     内容类型context-type不同:

  • soap1.1使用text/xml
  • soap1.2使用application/soap+xml

 

      命名空间Envelope xmlns不同:

  • soap1.1使用http://schemas.xmlsoap.org/soap/envelope/
  • soap1.2使用http://www.w3.org/2003/05/soap-envelope

http测试

package service;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.URL;public class HttpRequestSoap {public static void main(String[] args) throws IOException {//webservice地址String webservice_url = "http://127.0.0.1:12345/weather";//发送的soap协议内容String soap_xml = soap_xml("郑州");System.out.println(soap_xml);//创建urlURL url = new URL(webservice_url);//创建http链接对象HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();//设置请求方法httpURLConnection.setRequestMethod("POST");//设置Content-typehttpURLConnection.setRequestProperty("Content-type", "text/xml;charset=\"utf-8\"");//使用http进行输出httpURLConnection.setDoOutput(true);//使用http进行输入httpURLConnection.setDoInput(true);//通过输出流发送数据OutputStream outputStream = httpURLConnection.getOutputStream();outputStream.write(soap_xml.getBytes());outputStream.close();//接收服务端响应数据InputStream inputStream =  httpURLConnection.getInputStream();//使用buffer存在读取的数据byte[] buffer = new byte[1024];//使用字节输出流存储读取的数据ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();while(true){int len = inputStream.read(buffer);//如果流水读取完则退出循环if(len == -1){break;}byteArrayOutputStream.write(buffer,0,len);}//得到响应数据String response_string = byteArrayOutputStream.toString();System.out.println(response_string);}//soap协议内容public static String soap_xml(String cityName){String soap_xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+ "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">"+ "<S:Body>"+ "<ns2:queryWeather xmlns:ns2=\"http://service/\">"+ "<arg0>"+ cityName  + "</arg0>"+ "</ns2:queryWeather>"+ "</S:Body>"+ "</S:Envelope>";return soap_xml;}}

4.spring+webservice+jaxrs

spring+webservice+jaxrs

5.spring+webservice+jaxws

jax-ws的配置与jaxrs的配置十分相似,此处照搬的官网给的源码例子(参考cxf+spring).新建一个maven的web项目
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>stu</groupId><artifactId>stu</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>cxf</artifactId><packaging>war</packaging><dependencies><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-jaxws</artifactId><version>3.1.12</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.1.12</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http-jetty</artifactId><version>3.1.12</version></dependency><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-webapp</artifactId><version>9.2.21.v20170120</version></dependency><!-- spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.4.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>4.3.4.RELEASE</version></dependency></dependencies></project>
service
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */// START SNIPPET: servicepackage demo.spring.service;import javax.jws.WebService;@WebServicepublic interface HelloWorld {    String sayHi(String text);}// END SNIPPET: service
serviceImpl
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */// START SNIPPET: servicepackage demo.spring.service;import javax.jws.WebService;@WebService(endpointInterface = "demo.spring.service.HelloWorld")public class HelloWorldImpl implements HelloWorld {    public String sayHi(String text) {        System.out.println("sayHi called");        return "Hello " + text;    }}// END SNIPPET: service
server
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */package demo.spring.service;import org.eclipse.jetty.server.Handler;import org.eclipse.jetty.server.handler.DefaultHandler;import org.eclipse.jetty.server.handler.HandlerCollection;import org.eclipse.jetty.webapp.WebAppContext;public class Server {    protected Server() throws Exception {        System.out.println("Starting Server");        /**         * Important: This code simply starts up a servlet container and adds         * the web application in src/webapp to it. Normally you would be using         * Jetty or Tomcat and have the webapp packaged as a WAR. This is simply         * as a convenience so you do not need to configure your servlet         * container to see CXF in action!         */        org.eclipse.jetty.server.Server server = new org.eclipse.jetty.server.Server(9002);        WebAppContext webappcontext = new WebAppContext();        webappcontext.setContextPath("/");        //此处对应你的war包        webappcontext.setWar("target/cxf-0.0.1-SNAPSHOT.war");        HandlerCollection handlers = new HandlerCollection();        handlers.setHandlers(new Handler[] {webappcontext, new DefaultHandler()});        server.setHandler(handlers);        server.start();        System.out.println("Server ready...");        server.join();    }    public static void main(String args[]) throws Exception {        new Server();    }}
client
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */package demo.spring.client;import org.springframework.context.support.ClassPathXmlApplicationContext;import demo.spring.service.HelloWorld;public final class Client {    private Client() {    }    public static void main(String args[]) throws Exception {        // START SNIPPET: client        ClassPathXmlApplicationContext context             = new ClassPathXmlApplicationContext(new String[] {"client-beans.xml"});        HelloWorld client = (HelloWorld)context.getBean("client");        String response = client.sayHi("Joe");        System.out.println("Response: " + response);        System.exit(0);        // END SNIPPET: client    }}
web-info 下的两个xml
web.xml
<?xml version="1.0" encoding="UTF-8"?><!--  Licensed to the Apache Software Foundation (ASF) under one  or more contributor license agreements. See the NOTICE file  distributed with this work for additional information  regarding copyright ownership. The ASF licenses this file  to you under the Apache License, Version 2.0 (the  "License"); you may not use this file except in compliance  with the License. You may obtain a copy of the License at  http://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing,  software distributed under the License is distributed on an  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY  KIND, either express or implied. See the License for the  specific language governing permissions and limitations  under the License.--><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee           http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">    <display-name>cxf</display-name>    <servlet>        <description>Apache CXF Endpoint</description>        <display-name>cxf</display-name>        <servlet-name>cxf</servlet-name>        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>cxf</servlet-name>        <url-pattern>/services/*</url-pattern>    </servlet-mapping>    <session-config>        <session-timeout>60</session-timeout>    </session-config></web-app>
cxf-servlet.xml
<?xml version="1.0" encoding="UTF-8"?><!--        Licensed to the Apache Software Foundation (ASF) under one        or more contributor license agreements. See the NOTICE file        distributed with this work for additional information        regarding copyright ownership. The ASF licenses this file        to you under the Apache License, Version 2.0 (the        "License"); you may not use this file except in compliance        with the License. You may obtain a copy of the License at                http://www.apache.org/licenses/LICENSE-2.0                Unless required by applicable law or agreed to in writing,        software distributed under the License is distributed on an        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY        KIND, either express or implied. See the License for the        specific language governing permissions and limitations        under the License.--><!-- START SNIPPET: beans --><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"><!--     <import resource="classpath:META-INF/cxf/cxf.xml"/>    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/> -->    <jaxws:endpoint id="helloWorld" implementor="demo.spring.service.HelloWorldImpl" address="/HelloWorld"/></beans><!-- END SNIPPET: beans -->
resource目录下的client-beans.xml
<?xml version="1.0" encoding="UTF-8"?><!--        Licensed to the Apache Software Foundation (ASF) under one        or more contributor license agreements. See the NOTICE file        distributed with this work for additional information        regarding copyright ownership. The ASF licenses this file        to you under the Apache License, Version 2.0 (the        "License"); you may not use this file except in compliance        with the License. You may obtain a copy of the License at                http://www.apache.org/licenses/LICENSE-2.0                Unless required by applicable law or agreed to in writing,        software distributed under the License is distributed on an        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY        KIND, either express or implied. See the License for the        specific language governing permissions and limitations        under the License.--><!-- START SNIPPET: beans --><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd">    <bean id="client" class="demo.spring.service.HelloWorld" factory-bean="clientFactory" factory-method="create"/>    <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">        <property name="serviceClass" value="demo.spring.service.HelloWorld"/>        <property name="address" value="http://localhost:9002/services/HelloWorld"/>    </bean></beans><!-- END SNIPPET: beans -->
测试:先运行server ,然后运行client,打印Response: Hello Joe  ok.
webservice使用总结:

       Webservice发送xml数据其实是将xml数据作为大字符串发送,工作量主要在解析xml数据上。虽然解析xml数据比较麻烦但是webservice接口简单,大家遵守xml格式开发接口,这种方式在企业中也较常用。

       数据量大的xml建议使用SAX解析提高解析速度。

      soap协议支持面向对象开发,传输对象比传输xml方便,但是之所以企业中开发webservice采用xml描述请求和响应的数据是因为xml数据格式是一种跨平台的标准数据格式,企业在开发中会选择一些标准的数据格式作为接口协议,比如:xml、json。

    实际应用时根据企业中的开发需求确定是传输java对象还是xml串以及json串等。

原创粉丝点击