webservice_webservicedemo - CSDN
webservice 订阅
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。 [1]  Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。 展开全文
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。 [1]  Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。Web Service也很容易部署, 因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
信息
类    型
应用程序
平    台
独立平台
作    用
交换数据或集成
中文名
Web Service
外文名
Web Service
Web Service历史
web广泛用到的技术:他们的特点是其开放性,跨平台性,开放性正是Web services的基础。近几年来,Internet的迅猛发展使其成为全球信息传递与共享的巨大的资源库。越来越多的网络环境下的Web应用系统被建立起来,利用HTML、CGI等Web技术可以轻松地在Internet环境下实现电子商务、电子政务等多种应用。然而这些应用可能分布在不同的地理位置,使用不同的数据组织形式和操作系统平台,加上应用不同所造成的数据不一致性,使得如何将这些高度分布的数据集中起来并得以充分利用成为急需解决的问题。随着网络技术、网络运行理念的发展,人们提出一种新的利用网络进行应用集成的解决方案——Web Service。Web Service是一种新的Web应用程序分支,其可以执行从简单的请求到复杂商务处理的任何功能。一旦部署以后,其他Web Service应用程序可以发现并调用它部署的服务。因此,Web Service是构造分布式、模块化应用程序和面向服务应用集成的最新技术和发展趋势。
收起全文
精华内容
参与话题
  • 比 WCF 更简单、更通用,比 WebService 更节省流量、更简洁,Web API 是一个轻量级的框架,非常适合构建移动客户端服务。 WebApi 基础+进阶 实战视频教程,整个课程分为两个阶段,基础和进阶(提高)阶段,两个...
  • WebService技术详解 (一)

    万次阅读 多人点赞 2017-07-25 18:01:18
    WebServiceWebService简介Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三... 简单的说,WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。所谓跨编程语言和跨操作平台,

    WebService

    WebService简介

    Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。

    简单的说,WebService就是一种跨编程语言和跨操作系统平台的远程调用技术。所谓跨编程语言和跨操作平台,就是说服务端程序采用java编写,客户端程序则可以采用其他编程语言编写,反之亦然。跨操作系统平台则是指服务端程序和客户端程序可以在不同的操作系统上运行。 远程调用,就是一台计算机的应用可以调用其他计算机上的应用。例如:支付宝,支付宝并没有银行卡等数据,它只是去调用银行提供的接口来获得数据。还有天气预报等,也是气象局把自己的系统服务以webservice服务的形式暴露出来,让第三方网站和程序可以调用这些服务功能。

    WebService原理

    XML,SOAP和WSDL就是构成WebService平台的三大技术 。

    • WebService采用Http协议来在客户端和服务端之间传输数据。WebService使用XML来封装数据,XML主要的优点在于它是跨平台的。

    • WebService通过HTTP协议发送请求和接收结果时,发送的请求内容和结果内容都采用XML格式封装,并增加了一些特定的HTTP消息头,以说明HTTP消息的内容格式,这些特定的HTTP消息头和XML内容格式就是SOAP协议规定的。

    • WebService服务器端首先要通过一个WSDL文件来说明自己有什么服务可以对外调用。简单的说,WSDL就像是一个说明书,用于描述WebService及其方法、参数和返回值。 WSDL文件保存在Web服务器上,通过一个url地址就可以访问到它。客户端要调用一个WebService服务之前,要知道该服务的WSDL文件的地址。WebService服务提供商可以通过两种方式来暴露它的WSDL文件地址:1.注册到UDDI服务器,以便被人查找;2.直接告诉给客户端调用者。

    WebService交互的过程就是,WebService遵循SOAP协议通过XML封装数据,然后由Http协议来传输数据。

    JAVA WebService规范

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

    (1)JAX-WS:

    JAX-WS(Java API For XML-WebService)。早期的基于SOAP 的JAVA 的Web 服务规范JAX-RPC(java API For XML-Remote Procedure Call)目前已经被JAX-WS 规范取代,JAX-WS 是JAX-RPC 的演进版本,但JAX-WS 并不完全向后兼容JAX-RPC,二者最大的区别就是RPC/encoded 样式的WSDL,JAX-WS 已经不提供这种支持。JAX-RPC 的API 从JAVA EE5 开始已经移除,如果你使用J2EE1.4,其API 位于javax.xml.rpc.包。JAX-WS(JSR 224)规范的API 位于javax.xml.ws.包,其中大部分都是注解,提供API 操作Web 服务(通常在客户端使用的较多,由于客户端可以借助SDK 生成,因此这个包中的API 我们较少会直接使用)。

    (2)JAXM&SAAJ:

    JAXM(JAVA API For XML Message)主要定义了包含了发送和接收消息所需的API,相当于Web 服务的服务器端,其API 位于javax.messaging.*包,它是Java EE 的可选包,因此你需要单独下载。

    SAAJ(SOAP With Attachment API For Java,JSR 67)是与JAXM 搭配使用的API,为构建SOAP 包和解析SOAP 包提供了重要的支持,支持附件传输,它在服务器端、客户端都需要使用。这里还要提到的是SAAJ 规范,其API 位于javax.xml.soap.*包。

    JAXM&SAAJ 与JAX-WS 都是基于SOAP 的Web 服务,相比之下JAXM&SAAJ 暴漏了SOAP更多的底层细节,编码比较麻烦,而JAX-WS 更加抽象,隐藏了更多的细节,更加面向对象,实现起来你基本上不需要关心SOAP 的任何细节。那么如果你想控制SOAP 消息的更多细节,可以使用JAXM&SAAJ。

    (3)JAX-RS:

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

    WebService入门案例

    服务端的实现

    我们来实现一个天气系统的案例,客户端发送城市名称,服务器端回应相应的天气。

    1.  编写SEI(Service Endpoint Interface),SEI在webservice中称为portType,在java中就是普通接口 
    
    public interface WeatherInterface {
        public String queryWeather(String cityName);
    }
    
    2.  编写SEI实现类,此类作为webservice提供服务类 
    
    @WebService     //@WebService表示该类是一个服务类,需要发布其中的public的方法
    public class WeatherInterfaceImpl implements WeatherInterface {
    
        @Override
        public String queryWeather(String cityName) {
            System.out.println("获取城市名"+cityName);
            String weather="暴雨";    
            return weather;
        }
    
    }
    3.  第三步:发布服务,Endpoint类发布服务,publish方法,两个参数:1.服务地址;2.服务实现类 
    
    public class WeatherServer {
        public static void main(String[] args) {
            Endpoint.publish("http://127.0.0.1:12345/weather", new WeatherInterfaceImpl());
        }
    }
    
    4. 测试服务是否发布成功,通过阅读wsdl,确定客户端调用的接口、方法、参数和返回值存在,证明服务发布成功
    
    //我们在浏览器输入 http://127.0.0.1:12345/weather?wsdl 来获取wsdl文件进行阅读
    
    //wsdl,是以XML文件形式来描述WebService的”说明书”,有了说明书,我们才可以知道如何使用或是调用这个服务.
    
    //现在我们还不知道怎么去阅读,后面我们会详解,只要能获取到,就能确定WebService服务发布成功 

    这里写图片描述

    客户端的实现

    //客户端调用服务有很多种方法,我们先用工具生成客户端代码,后面会详解  
    
    //wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).当然,无论服务器端的WebService是用什么语言写的,都可以生成调用webservice的客户端代码。
    
    1.创建一个客户端空项目,cmd命令行进入此项目的src目录
      使用以下命令生成客户端代码  
    
        wsimport -s . http://127.0.0.1:12345/weather?wsdl
    
        -s是指编译出源代码文件,后面的.(点)指將代码放到当前目录下.
         最后面的http….是指获取wsdl说明书的地址
    

    这里写图片描述

    2.编写客户端
    public class WeatherClient {
    
        public static void main(String[] args) {
            //创建服务视图,视图是从wsdl文件的service标签的name属性获取
            WeatherInterfaceImplService weatherInterfaceImplService=new WeatherInterfaceImplService();  
    
            //获取服务实现类,实现类从wsdl文件的portType的name属性获取
            WeatherInterfaceImpl weatherInterfaceImpl=weatherInterfaceImplService.getPort(WeatherInterfaceImpl.class); 
            //获取查询方法,从portType的operation标签获取
            String weather=weatherInterfaceImpl.queryWeather("北京");
            System.out.println(weather);
    
        }
    
    }
    

    至此,我们的客户端就可以获取远程服务端的数据,接下来我们来详解一下各个部分。

    WSDL

    WSDL(Web Services Description Language), web服务描述语言,他是webservice服务端使用说明书,说明服务端接口、方法、参数和返回值,WSDL是随服务发布成功,自动生成,无需编写。

    文档结构

    这里写图片描述

    Service:相关端口的集合,包括其关联的接口、操作、消息等。

    Binding:特定端口类型的具体协议和数据格式规范

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

    message: 定义一个操作(方法)的数据参数

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

    阅读方式

    WSDL文档应该从下往上阅读。

    1.先看service标签,看相应port的binding属性,然后通过值查找上面的binding标签。

    2.通过binding标签可以获得具体协议等信息,然后查看binding的type属性

    3.通过binding的type属性,查找对应的portType,可以获得可操作的方法和参数、返回值等。

    4.通过portType下的operation标签的message属性,可以向上查找message获取具体的数据参数信息。

    SOAP

    SOAP即简单对象访问协议,他是使用http发送的XML格式的数据,它可以跨平台,跨防火墙,SOAP不是webservice的专有协议。

    SOAP=http+xml

    SOAP结构

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

    这里写图片描述

    我们来看一下我们上面天气程序发送的数据的格式,这需要一个工具TCP/IP Monitor ,Eclipse自带的Debug工具之一,用于捕获Http、TCP/IP协议包。原理是一个代理服务,客户端先把数据发送到代理服务,然后代理服务再把数据发送到服务器,这样就能获取请求数据和响应数据。

    第一步:打开这个工具,选择other,然后输入TCP/IP Monitor

    这里写图片描述

    第二步:设置要代理的服务器

    这里写图片描述

    第三步:详细设置

    第一个参数是代理服务器端口,我们设置为54321
    第二个参数是被代理服务器的地址,第三个参数是被代理服务器的端口
    第四个参数要选择为TCP/IP
    

    这里写图片描述

    第四步:检测是否设置成功,我们访问代理服务器来获得wsdl文件

    这里写图片描述

    第五步:设置成功后,我们需要改一下客户端要连接的服务器,改成代理服务器的端口

    将WeatherInterfaceImplService里的所有原来地址的端口改为54321
    

    这里写图片描述

    第六步:我们启动我们的客户端,获取请求数据和响应数据

    
    请求 
    
    //先发送get请求,去获得wsdl文件,然后获得方法、参数等信息
    GET /weather?wsdl HTTP/1.1
    User-Agent: Java/1.8.0_111
    Host: 127.0.0.1:54321
    Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
    Connection: keep-alive
    
    //发送数据
    POST /weather HTTP/1.1
    Accept: text/xml, multipart/related
    Content-Type: text/xml; charset=utf-8
    SOAPAction: "http://ws.cad.com/WeatherInterfaceImpl/queryWeatherRequest"
    User-Agent: JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e
    Host: 127.0.0.1:54321
    Connection: keep-alive
    Content-Length: 203
    
    <?xml version="1.0" ?>
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
    <ns2:queryWeather xmlns:ns2="http://ws.cad.com/">
    <arg0>北京</arg0>
    </ns2:queryWeather>
    </S:Body>
    </S:Envelope>
    
    响应数据 
    
    HTTP/1.1 200 OK
    Date: Tue, 25 Jul 2017 05:05:58 GMT
    Transfer-encoding: chunked
    Content-type: text/xml;charset=utf-8
    
    //响应wsdl内容,来获得方法、参数等信息
    899
    <?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><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://ws.cad.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.cad.com/" name="WeatherInterfaceImplService">
    <types>
    <xsd:schema>
    <xsd:import namespace="http://ws.cad.com/" schemaLocation="http://127.0.0.1:54321/weather?xsd=1"></xsd:import>
    </xsd:schema>
    </types>
    <message name="queryWeather">
    <part name="parameters" element="tns:queryWeather"></part>
    </message>
    <message name="queryWeatherResponse">
    <part name="parameters" element="tns:queryWeatherResponse"></part>
    </message>
    <portType name="WeatherInterfaceImpl">
    <operation name="queryWeather">
    <input wsam:Action="http://ws.cad.com/WeatherInterfaceImpl/queryWeatherRequest" message="tns:queryWeather"></input>
    <output wsam:Action="http://ws.cad.com/WeatherInterfaceImpl/queryWeatherResponse" message="tns:queryWeatherResponse"></output>
    </operation>
    </portType>
    <binding name="WeatherInterfaceImplPortBinding" type="tns:WeatherInterfaceImpl">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
    <operation name="queryWeather">
    <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="WeatherInterfaceImplService">
    <port name="WeatherInterfaceImplPort" binding="tns:WeatherInterfaceImplPortBinding">
    <soap:address location="http://127.0.0.1:54321/weather"></soap:address>
    </port>
    </service>
    </definitions>
    0
    
    //响应数据
    HTTP/1.1 200 OK
    Date: Tue, 25 Jul 2017 05:05:59 GMT
    Transfer-encoding: chunked
    Content-type: text/xml; charset=utf-8
    
    df
    <?xml version="1.0" ?>
    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:queryWeatherResponse xmlns:ns2="http://ws.cad.com/">
        <return>暴雨</return> 
        </ns2:queryWeatherResponse> 
    </S:Body>
    </S:Envelope>
    0
    

    UDDI

    UDDI 是一种目录服务,企业可以使用它对 Web services 进行注册和搜索。
    如果我们要使用一种服务,但是不知道地址(wsdl等),我们就可以在UDDI中查找。
    大部分情况下,我们都是知道服务地址的。

    Webservice的客户端调用方式

    一:生成客户端调用方式

    wsimport是jdk自带的webservice客户端工具,可以根据wsdl文档生成客户端调用代码(java代码).
    wsimport.exe位于JAVA_HOME\bin目录下 
    常用参数为:
            -d<目录>  - 将生成.class文件。默认参数。
            -s<目录> - 将生成.java文件。
            -p<生成的新包名> -将生成的类,放于指定的包下
    

    调用公网的手机归属地查询服务

    公网服务地址 (里面提供了很多免费调用的服务)
    http://www.webxml.com.cn/zh_cn/index.aspx

    第一步:wsimport生成客户端代码 
    
    wsimport -p cn.cad.mobile -s . http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
    
    会出现一些警告,是因为服务端提供的一些方法是SOAP1.2标准的,这个工具没有实现SOAP1.2标准的生成方式。    
    

    这里写图片描述

    第二步:查看wsdl文件,获取我们需要的信息 

    这里写图片描述

    第三步:根据获取到的服务名等信息来创建我们的客户端  
    
    public class MobileClient {
    
        public static void main(String[] args) {
            //创建服务视图
            MobileCodeWS mobileCodeWS=new MobileCodeWS();
            //获取服务实现类
            MobileCodeWSSoap mobileCodeWSSoap= mobileCodeWS.getPort(MobileCodeWSSoap.class);
            //调用查询方法
            String message=mobileCodeWSSoap.getMobileCodeInfo("xxxxxxxx", null);
            System.out.println(message);
    
        }
    }
    
    第四步:获取到信息 

    这里写图片描述

    还有天气等服务,自己可以去实现一下。

    该种方式使用简单,但一些关键的元素在代码生成时写死在生成代码中,不方便维护,所以仅用于测试。

    二:service编程调用方式

    public class MobileClient2 {
    
        public static void main(String[] args) throws IOException {
            //创建WSDL文件的URL
            URL wsdlDocumentLocation=new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl"); 
            //创建服务名称
            //1.namespaceURI - 命名空间地址
            //2.localPart - 服务视图名
            QName serviceName=new QName("http://WebXml.com.cn/","MobileCodeWS");
            Service service=Service.create(wsdlDocumentLocation, serviceName);
    
            //获取服务实现类
            MobileCodeWSSoap mobileCodeWSSoap= service.getPort(MobileCodeWSSoap.class);
            //调用方法
            String message=mobileCodeWSSoap.getMobileCodeInfo("XXXXXXX", null);
            System.out.println(message);
    
        }
    
    }

    该种方式可以自定义命名空间,服务视图名等元素,方便以后维护,是一种标准的开发方式 。

    三:HttpURLConnection调用方式

    这种方式是由自己编写客户端,不再由工具生成,比较麻烦。

    开发步骤: 
    
            第一步:创建服务地址
    
            第二步:打开一个通向服务地址的连接
    
            第三步:设置参数
    
            第四步:组织SOAP数据,发送请求
    
            第五步:接收服务端响应 
    
    public class MobileClient2 {
    
        public static void main(String[] args) throws IOException {
                    //第一步:创建服务地址,不是WSDL地址
                    URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");
                    //第二步:打开一个通向服务地址的连接
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    //第三步:设置参数
                    //3.1发送方式设置:POST必须大写
                    connection.setRequestMethod("POST");
                    //3.2设置数据格式:content-type
                    connection.setRequestProperty("content-type", "text/xml;charset=UTF-8");
                    //3.3设置输入输出,因为默认新创建的connection没有读写权限,
                    connection.setDoInput(true);
                    connection.setDoOutput(true);
    
                    //第四步:组织SOAP数据,发送请求
                    String soapXML = getXML("XXXXXXX");
                    OutputStream os = connection.getOutputStream();
                    os.write(soapXML.getBytes());
                    //第五步:接收服务端响应,打印
                    int responseCode = connection.getResponseCode();
                    if(200 == responseCode){//表示服务端响应成功
                        InputStream is = connection.getInputStream();
                        //将字节流转换为字符流
                        InputStreamReader isr = new InputStreamReader(is,"utf-8");
                        //使用缓存区
                        BufferedReader br = new BufferedReader(isr);
    
                        StringBuilder sb = new StringBuilder();
                        String temp = null;
                        while(null != (temp = br.readLine())){
                            sb.append(temp);
                        }
                        System.out.println(sb.toString());
    
                        is.close();
                        isr.close();
                        br.close();
                    }
    
                    os.close();
                }
    
        //组织数据,将数据拼接一下
        public static String getXML(String phoneNum){
            String soapXML = "<?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>"+phoneNum+"</mobileCode>"
                  +"<userID></userID>"
                +"</getMobileCodeInfo>"
              +"</soap:Body>"
            +"</soap:Envelope>";
            return soapXML;
        }
    }

    这里写图片描述

    使用注解修改WSDL内容

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

    WebService的注解都位于javax.jws包下: 
    
    @WebService-定义服务,在类上边
        targetNamespace:指定命名空间
        name:portType的名称
        portName:port的名称
        serviceName:服务名称
        endpointInterface:SEI接口地址,如果一个服务类实现了多个接口,只需要发布一个接口的方法,可通过此注解指定要发布服务的接口。 
    
    @WebMethod-定义方法,在公开方法上边
        operationName:方法名
        exclude:设置为true表示此方法不是webservice方法,反之则表示webservice方法,默认是false 
    
    @WebResult-定义返回值,在方法返回值前边
        name:返回结果值的名称 
    
    @WebParam-定义参数,在方法参数前边
        name:指定参数的名称
    
    //以我们前面做的天气案例为例子
    
    @WebService(
            targetNamespace="http://service.cad.com",
            portName="WeatherSOAPPort",
            serviceName="WeatherWSS",
            name="WeatherSOAP"  
    )
    public class WeatherInterfaceImpl implements WeatherInterface {
    
        @WebMethod(
                operationName="getWeather",
                exclude=false
        )
        public @WebResult(name="result")String queryWeather(@WebParam(name="cityName")String cityName) {
            System.out.println("获取城市名"+cityName);
            String weather="暴雨";    
            return weather;
        }
    
    }
    然后重新发布服务,我们再访问wsdl文件,就可以看到我们改变的内容 

    这里写图片描述

    展开全文
  • 实现webservice的几种方式

    万次阅读 多人点赞 2018-10-25 18:09:52
    1, WebService是两个系统的远程调用,使两个系统进行数据交互,如应用:天气预报服务、银行ATM取款、使用邮箱账号登录各网站等。 2, WebService之间的调用是跨语言的调用。Java、.Net、php,发送Http请求,使用的...

    1. 概念了解

    • WebService是两个系统的远程调用,使两个系统进行数据交互,如应用:天气预报服务、银行ATM取款、使用邮箱账号登录各网站等。

    • WebService之间的调用是跨语言的调用。Java、.Net、php,发送Http请求,使用的数据格式是XML格式。

    • webxml.com.cn上面有一些免费的WebService服务,可以进去看看。

    2. 客户端实现的几种方式

    2.1 Wsimport实现方式

    概念理解:

    • WSDL – WebService Description Language – Web服务描述语言。
    • 通过XML形式说明服务在什么地方-地址。address location
    • 通过XML形式说明服务提供什么样的方法 – 如何调用。operation

    注意:该种方式使用简单,但一些关键的元素在代码生成时写死到生成代码中,不方便维护,所以仅用于测试。

    实现方式:
    (1)Wsimport命令介绍
    Wsimport就是jdk(1.6版本之后)提供的的一个工具,他的作用就是根据WSDL地址生成客户端代码;
    Wsimport位置JAVA_HOME/bin
    Wsimport常用的参数:
    -s,生成java文件的
    -d,生成class文件的,默认的参数
    -p,指定包名的,如果不加该参数,默认包名就是wsdl文档中的命名空间的倒序;

    public class MobileClient {
        public static void main(String[] args) {
             //创建服务访问点集合的对象 ,wsdl文档中:<wsdl:service name="MobileCodeWS">
            MobileCodeWS mobileCodeWS = new MobileCodeWS();
            
            //获取服务实现类,wsdl中:<wsdl:portType name="MobileCodeWSSoap">
            MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getPort(MobileCodeWSSoap.class);
            
            //根据服务访问点的集合中的服务访问点的绑定对象来获得绑定的服务类
            MobileCodeWSSoap mobileCodeWSSoap = mobileCodeWS.getMobileCodeWSSoap();
            String mobileCodeInfo = mobileCodeWSSoap.getMobileCodeInfo("18518114962", "");
            System.out.println(mobileCodeInfo);
        }
    }
    

    2.2 service实现方式

    service编程调用方式 ,这种方式其实就是只需引用服务的方法类就行,不需要全部引用。

    public class ServiceClient {  
    
        public static void main(String[] args) throws IOException {  
            //创建WSDL的URL,注意不是服务地址  
            URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl");  
    
            //创建服务名称  
            //1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace)
            //2.localPart - 服务视图名  ,wsdl文档中:<wsdl:service name="MobileCodeWS">
            QName qname = new QName("http://WebXml.com.cn/", "MobileCodeWS");  
            
             / /wsdlDocumentLocation - wsdl地址 ,serviceName - 服务名称 
            Service service = Service.create(url, qname);  
            //获取服务实现类  wsdl中:<wsdl:portType name="MobileCodeWSSoap">
            MobileCodeWSSoap mobileCodeWSSoap = service.getPort(MobileCodeWSSoap.class);  
            //调用查询方法  
            String result = mobileCodeWSSoap.getMobileCodeInfo("1866666666", "");  
            System.out.println(result);  
        }  
    } 
    

    2.3 HttpURLConnection调用方式

    操作步骤,开发步骤:
    第一步:创建服务地址
    第二步:打开一个通向服务地址的连接
    第三步:设置参数 设置POST,POST必须大写,如果不大写,报异常
    第四步:组织SOAP数据,发送请求
    第五步:接收服务端响应,打印

    public class HttpURLConectionMode {
        public static void main(String[] args) throws IOException {
            //第一步:创建服务地址,不是WSDL地址 
            URL url = new URL("http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx");  
            //第二步:打开一个通向服务地址的连接  
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
            //第三步:设置参数  
            //3.1发送方式设置:POST必须大写  
            connection.setRequestMethod("POST");
            //3.2设置数据格式:content-type  
            connection.setRequestProperty("content-type", "text/xml;charset=utf-8");  
            //3.3设置输入输出,因为默认新创建的connection没有读写权限,  
            connection.setDoInput(true);  
            connection.setDoOutput(true);
    
            //第四步:组织SOAP数据,发送请求  
            String soapXML = getXML("15226466316");
            OutputStream os = connection.getOutputStream();  
            os.write(soapXML.getBytes()); 
    
            //第五步:接收服务端响应,打印(xml格式数据)
            int responseCode = connection.getResponseCode();  
            if(200 == responseCode){//表示服务端响应成功
                InputStream is = null;
                InputStreamReader isr = null;
                BufferedReader br = null;
                StringBuilder sb = null;
                try {
                    is = connection.getInputStream();  
                    isr = new InputStreamReader(is);  
                    br = new BufferedReader(isr);  
    
                    sb = new StringBuilder();  
                    String temp = null;  
                    while(null != (temp = br.readLine())){  
                        sb.append(temp);  
                    }
                     System.out.println(sb.toString()); 
                } catch (Exception e) {
                    e.printStackTrace();
                    throw e;
                } finally {
                    br.close();
                    isr.close();
                    is.close();
                }
            }  
    
            os.close();
        }
    
        public static String getXML(String phoneNum){  
            String soapXML = "<?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>"+phoneNum+"</mobileCode>"  
                  +"<userID></userID>"  
                +"</getMobileCodeInfo>"  
              +"</soap:Body>"  
            +"</soap:Envelope>";  
            return soapXML;  
        }  
    
    }
    

    2.4 Ajax调用方式

    jsonp无法实现跨域,因为webservice服务的响应格式为xml格式;

    <!doctype html>  
    <html lang="en">  
     <head>  
      <meta charset="UTF-8">  
      <title>Document</title>  
      <script type="text/javascript">  
        function queryMobile(){  
            //创建XMLHttpRequest对象  
            var xhr = new XMLHttpRequest();  
            //打开连接  
            xhr.open("post","http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx",true);  
            //设置数据类型  
            xhr.setRequestHeader("content-type","text/xml;charset=utf-8");  
            //设置回调函数  
            xhr.onreadystatechange=function(){  
                //判断是否发送成功和判断服务端是否响应成功  
                if(4 == xhr.readyState && 200 == xhr.status){  
                    alert(xhr.responseText);  
                }  
            }  
            //组织SOAP协议数据  
            var soapXML = "<?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>"+document.getElementById("phoneNum").value+"</mobileCode>"  
                  +"<userID></userID>"  
                +"</getMobileCodeInfo>"  
              +"</soap:Body>"  
            +"</soap:Envelope>";  
            alert(soapXML);  
            //发送数据  
            xhr.send(soapXML);  
        }  
      </script>  
     </head>  
     <body>  
      手机号查询:<input type="text" id="phoneNum"/> <input type="button" value="查询" onclick="javascript:queryMobile();"/>  
     </body>  
    </html> 
    

    下面图是展示wsdl文档中的关键字段,以及对服务方法的如何使用以及功能描述

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    3 .服务端的实现

    服务端使用cfx+spring和注解实现服务端发布

    pom文件添加jar包

     <!-- 添加cxfwebservice依赖jar包  2018-07-05 -->
              <dependency>
                  <groupId>org.apache.cxf</groupId>
                  <artifactId>cxf-rt-frontend-jaxws</artifactId>
                  <version>2.5.1</version>
              </dependency>
              <dependency>
                  <groupId>org.apache.cxf</groupId>
                  <artifactId>cxf-rt-transports-http</artifactId>
                  <version>2.5.1</version>
              </dependency>
    

    web.xml添加配置

     <!-- cxf WEBSERVICE配置 -->
      <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>
                org.apache.cxf.transport.servlet.CXFServlet
            </servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/renewal/*</url-pattern>
      </servlet-mapping>
    

    spring配置文件添加配置

     <!-- 添加cxfwebservice文件  -->
         <import resource="classpath:META-INF/cxf/cxf.xml" />
         <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
         <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
         <!--下面的class属性值一定要跟你项目中服务实现类的包路径完全一致 -->
         <jaxws:endpoint id="renewalPaymentLock" implementor="com.sinosoft.sinopay.web.weixinpay.biz.service.impl.RenewalPaymentLockServiceImpl" address="/RenewalPaymentLock" />
    

    最终生成是地址是: ip/renewal/RenewalPaymentLock?wsdl (web.xml+springd拼接而成的)

    接口中伪代码实现:

    @WebService
    public interface RenewalPaymentLockService {
         @WebMethod
         public String  RenewalPaymentLock(String renewalJson);
    }
    

    实现类注解:

    @WebService(endpointInterface = "com.sinosoft.sinopay.web.weixinpay.biz.service.RenewalPaymentLockService")
    endpointInterface  是接口中的地址(包名)
    

    参考文章:https://blog.csdn.net/menghuanzhiming/article/details/78475785

    展开全文
  • 我的第一次WebService接口开发

    万次阅读 多人点赞 2019-05-09 16:58:09
    最近项目上需要对接WebService接口,之前从来没有用过,这次都遇见了。记录下基础的使用和我遇见的问题。 正文 概述 WebService接口百度一搜,各个介绍的都非常详细,由于刚开始没接触,看的也不是很懂。首先记住一...

    前言

    最近项目上需要对接WebService接口,之前从来没有用过,这次都遇见了。记录下基础的使用和我遇见的问题。
    如果是报错找答案的,建议直接查看最后 “遇见的问题” 或搜索文章内容查看对应的问题。

    正文

    概述

    WebService接口百度一搜,各个介绍的都非常详细,由于刚开始没接触,看的也不是很懂。首先记住一句话:WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
    跨编程语言和跨操作系统平台:也就是说Asp.net开发的WebService用java代码调用完全没问题,和操作系统也没有关系。
    远程调用技术:也就是说网络是通的就能用。
    那么这个WebService到底是干嘛用的?

    作用

    不同系统之间进行对接!比如现在需要使用第三方公司的短信服务,使用WebService来调用它的服务,只需要第三方公司提供一个接口调用文档和WebService地址,就能根据文档地址编程去调用它开放的短信服务,发送短信。为什么是WebService?

    优缺点

    回到那句话,WebService是一种跨编程语言和跨操作系统平台的远程调用技术。
    优点:
    1.跨语言和跨操作系统:因为WevService是通过Xml语言进行描述的,XML主要的优点在于它既与平台无关,又与厂商无关。
    2.远程调用技术:不用担心防火墙的问题。。。
    缺点:
    1.服务端接口方为webservice则客户端也必须使用webservice。
    2.因为webservice使用xml传输数据,因此性能上不能满足高并发。
    3.有点笨重。。。
    其实WebService并不是非常流行,往往RESTful就能够达到需要,但是遇到了笔记还是要做的。

    使用

    只介绍对接WebService接口,生成请自行百度。
    这次对接了java的WebService接口和C#写的WebService接口。

    CXF 调用java WebService

    首先看看提供的WebService接口地址:http://127.0.0.1:8080/jjh/webService/smsXXX?wsdl
    一般都是给到这种地址,访问地址可以看到这个接口的xml描述,可以通过这个描述来生成java代码到本地来方便使用,比如一些实体类,service方法。
    准确的来说可以使用JDK自带的和CXF提供的命令,直接生成java代码,这里只建议使用Apach的CXF,直接去官网下载最新的cxf包,进入bin目录下,打开命令窗口,使用cxf命令生成java代码,这里提供一个最基础的:wsdl2java -encoding utf-8 http://127.0.0.1:8080/jjh/webService/smsXXX?wsdl
    执行之后你的bin目录下面会生成java文件,有了java文件下面就可以根据java文件和第三方给的文档进行调用了。
    比如,生成了IhalloWorld.java和IService.java文件,发现IhalloWorld接口里面声明了sendSms(args…)方法。

    public static void main(String[] args) {  
            JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();  
            //要得到的对象,是根据本地IService 接口取得的。
            factoryBean.setServiceClass(IService .class);  
            //调用地址
            factoryBean.setAddress("http://127.0.0.1:8080/jjh/webService/smsXXX");  
            //通过webservice取到IService的实现类,这个实现类才是你真正想要的,里面包括了你需要的东西。
            IService service = (IService)factoryBean.create();  
            IhalloWorld hello = service.getHelloWorld("xxx");  
            System.out.println("Hello:"+hello.sendSms("XXX你好..."));  
        }  
    

    参考链接:
    JAVA webservice之CXF
    WebService学习整理-JDK的wsimport命令和cxf的wsdl2java命令的区别和使用
    java接口调用——webservice就是一个RPC而已
    cxf的wsdl2java命令和JDK的wsimport命令的区别和使用

    asmx

    下面又对接了一个C#写的WebService接口,比如链接为:http://127.0.0.1:81/WebServiceCS/service.asmx ,在这个链接后面加上?wsdl,即:
    http://127.0.0.1:81/WebServiceCS/service.asmx?wsdl 也是可以使用cxf生成java代码的,但是注意一点,这接口是C#写的,xml只描述出实体信息,生成类似实体类的文件,没有现成的接口使用。一般其实也用不到cxf来生成,作用不大。参考例子:

    public String sendMail(Object[] params) {
        String soapaction = "http://tempuri.org/"; // 域名,这是在server定义的,在链接里面看得到,下面介绍。
        String operationName = "Mail_Send";// 调用服务名
        Service service = new Service();
        String ret = "";
        try {
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);
            call.setOperationName(new QName(soapaction, operationName)); // 设置要调用的方法
            call.addParameter(new QName(soapaction, "vvvv"), // 需要传递的参数名
                    org.apache.axis.encoding.XMLType.XSD_STRING,
                    javax.xml.rpc.ParameterMode.IN);
            call.addParameter(new QName(soapaction, "jjj"), // 需要传递的参数名
                    org.apache.axis.encoding.XMLType.XSD_STRING,
                    javax.xml.rpc.ParameterMode.IN);
            call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);// (标准的返回类型)
            call.setUseSOAPAction(true);
            call.setSOAPActionURI(soapaction + operationName);//url,域名加方法名
            ret = (String) call.invoke(params);// 调用方法并传递参数,params包含参数
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return ret;
    }
    
    

    其中operationName服务名和soapaction域名都在你的链接中可以找到 http://127.0.0.1:81/WebServiceCS/service.asmx
    在这里插入图片描述
    其中参数params数组根据你服务需要的参数来传,比如需要一个规范的xml字符串作为参数,使用dom4j进行操作。

            Document doc = DocumentHelper.createDocument();
            //增加根节点
            Element books = doc.addElement("books");
            //增加子元素
            Element book1 = books.addElement("book");
            Element title1 = book1.addElement("title");
            Element author1 = book1.addElement("author");
    
            Element book2 = books.addElement("book");
            Element title2 = book2.addElement("title");
            Element author2 = book2.addElement("author");
    
            //为子节点添加属性
            book1.addAttribute("id", "001");
            //为元素添加内容
            title1.setText("Harry Potter");
            author1.setText("J K. Rowling");
    
            book2.addAttribute("id", "002");
            title2.setText("Learning XML");
            author2.setText("Erik T. Ray");
    
            OutputFormat format = OutputFormat.createCompactFormat();
            format.setIndent(true); //设置是否缩进
            format.setIndent("    "); //以四个空格方式实现缩进
            format.setNewlines(true); //设置是否换行
    
            //设置输出编码
            format.setEncoding("gb2312");
            StringWriter writer = new StringWriter();
            XMLWriter output = new XMLWriter(writer, format);
            try {
                output.write(doc);
                writer.close();
                output.close();
                System.out.println(writer.toString());//打印xml字符串
            }  catch (IOException e) {
                e.printStackTrace();
            }
    

    打印结果
    在这里插入图片描述

    参考链接:
    Java调用webservice的.asmx后缀接口
    java调用webservice接口(.asmx)

    遇见的问题

    说实话开发起来挺快的,毕竟人家提供接口,东西都是现成的,最要命的问题就是报错了。

    导包

    包没导好,错少不了,可以参考这个博主的包导一导试试java调用webservice接口(.asmx),遇见报错不要慌,参考一下这个解决:WebService几个常见的异常
    我这里遇到的一个问题就是:
    java.lang.NoClassDefFoundError: Could not initialize class org.apache.axis.client.AxisClient
    我是由于commons-logging.jar包依赖版本冲突导致的,commons-discovery.jar包里面依赖了commons-logging包,但是,我自己导了commons-logging包,我的解决是排查commons-discovery对commons-logging的依赖:

            <dependency>
                <groupId>commons-discovery</groupId>
                <artifactId>commons-discovery</artifactId>
                <version>0.5</version>
                <exclusions>
                    <exclusion>
                        <groupId>commons-logging</groupId>
                        <artifactId>commons-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.2</version>
            </dependency>
    

    参考的java.lang.NoClassDefFoundError博客。
    接下来我又遇见了新的问题,弄了很久:由于我上面用了CXF,引入了一些包和我现在调.asmx接口axis2引入包又版本冲突了,,,,这个真的没找到,项目一调用CXF的那个接口就报错:
    java.lang.RuntimeException: Cannot create a secure XMLInputFactory
    网上找了找解决办法:
    1.有说缺少包,导入woodstox-core-asl-4.4.1.jar和stax2-api-3.1.4.jar包。
    2.woodstox-core-asl包需要优先被加载,修改tomcat下,这个包在lib文件夹的名字,因为tomcat是按顺序来加载的,woodstox-core-asl改名为awoodstox-core-asl,让它优先加载。
    参考:
    解决 调用报错: “Cannot create a secure XMLInputFactory”
    java.lang.RuntimeException: Cannot create a secure XMLInputFactory解决方案

    但是,上面两个都没解决我的问题,我感觉原因还是版本冲突了,,,
    最后我找到了一个解决方法:
    CXF报安全性错误 Cannot create a secure XMLInputFactory
    大佬就是大佬,然后我就调用之前添加了这行代码:

    	System.setProperty(StaxUtils.ALLOW_INSECURE_PARSER, "true");
    

    完美,但是这个版本冲突估计是没救了,依赖太多了。
    idea插件没解决掉,然后查看maven依赖树来解决:
    我以为的maven依赖图是这样的(一览无余):
    在这里插入图片描述
    实际上是这样的:
    在这里插入图片描述
    对不起,一览无余,打扰了。。。能力有限,版本冲突我干不掉了。
    之前组长是建议我添加一个简单的web项目,里面只部署CXF 对接的接口供我项目调用,这样两个接口依赖的包就不会在一块有版本冲突了,我觉得这个方法还是很赞的!!!

    后续

    后面项目部署到tomcat上面,发现jar包还是冲突啦!!!
    大概错误就是这样

    Caused by: java.lang.NoSuchFieldError: REFLECTION
    
    at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.<init>(RuntimeModelBuilder.java:43)
     
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:344)
     
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:216)
     
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:76)
     
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:55)
     
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     
    at java.lang.reflect.Method.invoke(Method.java:498)
     
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
     
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
     
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:441)
     
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
     
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    
    

    一番搜索后参照:
    stackoverflow
    java.lang.NoSuchFieldError: REFLECTION
    发现是com.sun.xml.bind:jaxb-core和com.sun.xml.bind:jaxb-impl****两个包版本号不一致造成的冲突。首先查看jar包的依赖情况,使用idea查看依赖树,运行maven命令 mvn dependency:tree。
    在这里插入图片描述
    不使用idea也一样,在pom文件位置打开cmd面板,如下图,在路径处输入cmd回车,执行maven命令 mvn dependency:tree。
    在这里插入图片描述
    查看jar包依赖情况:
    在这里插入图片描述
    在这里插入图片描述
    分别搜索jaxb-impljaxb-core,发现它们是jar包axis2-jaxwscxf-rt-frontend-jaxws分别依赖的子包。版本号分别是2.1.7和2.2.11,我这里是取消了axis2-jaxws对jaxb-impl的依赖单独配置jaxb-impl的依赖,指定版本号和jaxb-core一致2.2.11
    在这里插入图片描述
    最后将打包后的jaxb相关包替换在tomcat的包,使得版本一致,到此版本冲突问题解决。

    参考地址集合

    JAVA webservice之CXF
    WebService学习整理-JDK的wsimport命令和cxf的wsdl2java命令的区别和使用
    java接口调用——webservice就是一个RPC而已
    cxf的wsdl2java命令和JDK的wsimport命令的区别和使用

    Java调用webservice的.asmx后缀接口
    java调用webservice接口(.asmx)

    WebService几个常见的异常
    java.lang.NoClassDefFoundError

    解决 调用报错: “Cannot create a secure XMLInputFactory”
    java.lang.RuntimeException: Cannot create a secure XMLInputFactory解决方案

    CXF报安全性错误 Cannot create a secure XMLInputFactory

    stackoverflow
    java.lang.NoSuchFieldError: REFLECTION
    maven dependency:tree中反斜杠的含义
    如何查看Maven项目中的jar包依赖树情况?

    展开全文
  • Java创建WebService服务及客户端实现

    万次阅读 多人点赞 2013-10-14 23:10:06
    简介 WebService是一种服务的提供方式,通过WebService,不同应用间相互间调用变的很方便,网络上有很多常用的WebService服务,如:...Java的WebService实现,比较流行的有Axis2、Jaxws,...

    简介       

           WebService是一种服务的提供方式,通过WebService,不同应用间相互间调用变的很方便,网络上有很多常用的WebService服务,如:http://developer.51cto.com/art/200908/147125.htm,不同的语言平台对WebService都有实现,Java的WebService实现,比较流行的有Axis2、Jaxws,本文介绍的是Axis2。

    Axis2下载和部署

           Axis2是Apache开发的一个开源项目,再次感叹Apache的伟大!

           下载地址:

           http://mirror.bit.edu.cn/apache/axis/axis2/java/core/1.6.2/axis2-1.6.2-war.zip

           将其内axis2.war解压到<Tomcat安装目录>/webapps下,启动Tomcat,war包会自动解压,访问http://localhost:8080/axis2/,如果看到欢迎主页,则说明部署成功。

    配置Axis2

           <Tomcat安装目录>/webapps/axis2/WEB-INF/conf/axis2.xml,配置其内两个属性,以便调试。

    <parameter name="hotdeployment">true</parameter><!-- 开启热部署,不需要重启即可部署服务 -->
    <parameter name="hotupdate">true</parameter><!-- 开启热更新,不需要重启即可更新服务 -->

    编写服务

           所谓服务就是编写一个类,写一些方法,方法返回数据,WebService客户端获取数据。

    public class HelloService {
    
    	public String sayHello() {
    		return "hello";
    	}
    	
    }

    零配置发布服务

           服务类创建好后,我们需要发布到服务器上,将HelloService.class放到<Tomcat安装目录>/webapps/axis2/WEB-INF/pojo下,pojo没有需要创建。

           至此,我们已经成功的创建了一个WebService服务了,so easy!

           再次访问http://localhost:8080/axis2/,点击Services,可以发现可用services中多了一个HelloService,其内有一个可用操作sayHello,说明发布成功。

    HelloService
    
    Service Description : No description available for this service
    
    Service EPR : http://localhost:8080/axis2/services/HelloService
    
    Service Status : Active
    
    
    Available Operations
    sayHello

           访问http://localhost:8080/axis2/services/HelloService,页面输出正是我们的返回值。

    <ns:sayHelloResponse xmlns:ns="http://ws.apache.org/axis2">
    <return>hello</return>
    </ns:sayHelloResponse>

           这里有两点需要注意:

           - 发布的类不能放在包里,既不能使用package关键字;

           - 默认的发布目录是pojo,可以在<Tomcat安装目录>/webapps/axis2/WEB-INF/conf/axis2.xml中增加目录,

    <deployer extension=".class" directory="<要增加的目录名称>" class="org.apache.axis2.deployment.POJODeployer" />

             要注意多个目录间WebService要唯一,否则会重名,重名后,先部署的会成功,后部署的会报错。

    services.xml配置文件发布服务

           虽然上面的方式不需要配置文件,但是其服务类不能放在包内,显然是不符合我们日常开发的,Axis2也允许带包的类发布WebService,如果不允许,估计就没人用了。

           首先写一个较复杂的服务类,多个方法,带参数,有返回值的。

    package webservice.test;
    
    /**
     * 计算器运算
     * 
     * @author gaoshuang
     */
    public class CalculateService {
    
    	// 加法
    	public float plus(float x, float y) {
    		return x + y;
    	}
    
    	// 减法
    	public float minus(float x, float y) {
    		return x - y;
    	}
    
    	// 乘法
    	public float multiply(float x, float y) {
    		return x * y;
    	}
    
    	// 除法
    	public float divide(float x, float y) {
    		if (y != 0)
    			return x / y;
    		else
    			return -1;
    	}
    }

           然后编写services.xml,该文件需要放在META-INF文件夹下。

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 服务名称 -->
    <service name="CalculateService">
    	<!-- 服务描述 -->
        <description>
    		加减乘除计算服务
        </description>
        <!-- 设置服务类 -->
        <parameter name="ServiceClass">
            com.runqianapp.webservice.test.CalculateService
        </parameter>
        <!-- 方法 -->
        <operation name="plus">
        	<!-- 方法处理器,RPCMessageReceiver为带返回值的处理器,
        	             RPCInOnlyMessageReceiver为不带返回值的处理器 -->
        	<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
        </operation>
        <operation name="minus">
        	<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
        </operation>
        <operation name="multiply">
        	<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
        </operation>
        <operation name="divide">
        	<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
                class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
        </operation>
    </service>

           最后将这两个文件打成jar包,不论用工具还是手动打,打的都是最外层的文件夹。

           

           我打的名字是server.jar,更改后缀为aar,所以最后是server.aar,Axis2建议使用aar发布WebService,将server.aar放到<Tomcat安装目录>/webapps/axis2/WEB-INF/services下,访问http://localhost:8080/axis2/services/listServices,多出了一个CalculateService,说明发布成功。

    CalculateService
    
    Service Description : CalculateService
    
    Service EPR : http://localhost:8080/axis2/services/CalculateService
    
    Service Status : Active
    
    
    Available Operations
    divide
    plus
    minus
    multiply

           分别访问:

           http://localhost:8080/axis2/services/CalculateService/plus?x=1&y=2

           http://localhost:8080/axis2/services/CalculateService/divide?x=1&y=2

           http://localhost:8080/axis2/services/CalculateService/minus?x=1&y=2

           http://localhost:8080/axis2/services/CalculateService/multiply?x=1&y=2
           

           也可以发布多个WebService,可以使用serviceGroup标签。

    <serviceGroup>
    <service name="myService1">
    	...
    </service>
    <service name="myService2">
    	...
    </service>
    </serviceGroup>

    客户端实现

           以上介绍的都是WebService服务创建及发布,那么有了一个WebService服务后,我们如何调用呢?只在浏览器上访问是没有意义的。

           下载Axis2客户端压缩包:http://mirror.esocc.com/apache/axis/axis2/java/core/1.6.2/axis2-1.6.2-bin.zip,并解压。

           新建工程WebServiceClientTest,将<Axis2客户端安装目录>/lib下所有jar包添加到工程中。编写客户端代码:

    package webservice.client.test;
    
    import javax.xml.namespace.QName;
    
    import org.apache.axis2.AxisFault;
    import org.apache.axis2.addressing.EndpointReference;
    import org.apache.axis2.client.Options;
    import org.apache.axis2.rpc.client.RPCServiceClient;
    
    public class Client1 {
    
    	/**
    	 * @param args
    	 * @throws AxisFault
    	 */
    	public static void main(String[] args) throws AxisFault {
    		// 使用RPC方式调用WebService
    		RPCServiceClient serviceClient = new RPCServiceClient();
    		Options options = serviceClient.getOptions();
    		// 指定调用WebService的URL
    		EndpointReference targetEPR = new EndpointReference(
    				"http://localhost:8080/axis2/services/CalculateService");
    		options.setTo(targetEPR);
    		// 调用方法的参数值
    		Object[] entryArgs = new Object[] {1, 2};
    		// 调用方法返回值的数据类型的Class对象
    		Class[] classes = new Class[] { float.class };
    		// 调用方法名及WSDL文件的命名空间
    		// 命名空间是http://localhost:8080/axis2/services/CalculateService?wsdl中wsdl:definitions标签targetNamespace属性
    		QName opName = new QName("http://test.webservice", "plus");
    		// 执行方法获取返回值
    		// 没有返回值的方法使用serviceClient.invokeRobust(opName, entryArgs)
    		Object result = serviceClient.invokeBlocking(opName, entryArgs, classes)[0];
    		System.out.println(result);
    		// out: 3.0
    	}
    
    }
    

           以上是实现了一个简单的WebSerivce客户端,调用CalculateService中的plus方法,由代码可见,这种调用方式比较杂乱,代码不太友好。

    wsdl2java简化客户端

           <Axis2客户端安装目录>/bin目录,其内有两个bat,wsdl2java.bat和java2wsdl.bat,可以实现WSDL文件和Java之间的互相转换。

           考虑到我们以后可能经常使用这些命令,设置环境变量,方便以后调用。在系统变量中加入AXIS2_HOME=<Axis2客户端安装目录>,path中追加;%AXIS2_HOME%\bin。

           启动命令提示符,进入WebServiceTestClient所在目录,运行:

    wsdl2java -uri http://localhost:8080/axis2/services/CalculateService?wsdl -p webservice.client.test -s

           参数说明:uri - wsdl文件路径,网络路径或本地路径,p - 打包,这里和上一个客户端实现类打在了一个包里,wsdl2java有很多参数,详细可以运行该命令去查看。

           执行后,如果没有报错,说明运行成功,刷新项目,该包下多出了一个CalculateServiceStub类,里面的代码极其复杂,还乱呼呼的,这我们不用管,调用该类。

    package webservice.client.test;
    
    import java.rmi.RemoteException;
    
    import webservice.client.test.CalculateServiceStub.Plus;
    
    public class Client2 {
    
    	/**
    	 * @param args
    	 * @throws RemoteException 
    	 */
    	public static void main(String[] args) throws RemoteException {
    		CalculateServiceStub stub = new CalculateServiceStub();
    		Plus plus = new Plus();
    		plus.setX(1);
    		plus.setY(2);
    		float result = stub.plus(plus).get_return();// 返回值自动转型,这也是强大之处
    		System.out.println(result);
    	}
    
    }

           如此做的好处就是调用时不需要在去查看WSDL,和正常使用一个类一样,对WebService的封装都由wsdl2java自动生成,代码更优雅、简洁。

    利用wsdl2java轻松使用第三方WebService服务

           有了wsdl2java,已知一个WSDL文件我们就可以轻松的生成WebService客户端供我们调用,给我们服务。文章开头给出的链接包含了一些第三方服务,有一个服务是生成随机个数中文,WSDL:http://www.webxml.com.cn/WebServices/RandomFontsWebService.asmx?wsdl,同样,启动命令提示符,进入项目路径,执行:

    wsdl2java -uri http://www.webxml.com.cn/WebServices/RandomFontsWebService.asmx?wsdl -p webservice.client.test -s

           调用该类:

    package webservice.client.test;
    
    import java.rmi.RemoteException;
    
    import webservice.client.test.RandomFontsWebServiceStub.ArrayOfString;
    import webservice.client.test.RandomFontsWebServiceStub.GetChineseFonts;
    
    public class ThirdClient {
    
    	/**
    	 * @param args
    	 * @throws RemoteException 
    	 */
    	public static void main(String[] args) throws RemoteException {
    		RandomFontsWebServiceStub stub = new RandomFontsWebServiceStub();
    		GetChineseFonts getChineseFonts = new GetChineseFonts();
    		getChineseFonts.setByFontsLength(10);// 免费使用有限制,最多8个
    		ArrayOfString result = stub.getChineseFonts(getChineseFonts).getGetChineseFontsResult();
    		for(String str : result.getString()) {
    			System.out.println(str);
    		}
    	}
    
    }

    源码下载

           文中代码尽在下面链接中,免积分下载。

           http://download.csdn.net/download/ghsau/6400843

           (完)

           本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/12714965

     

    展开全文
  • WebService是什么

    万次阅读 多人点赞 2018-03-26 11:16:44
    WebService是什么鬼?全华班 2018-03-23 14:56:35喜欢就点击上面蓝色字,更多精彩!导读 | 精选一、什么是Web Service1. 什么是Web Service呢?从表面上看,WebService就是一个应用程序,它向外界暴露出一个能够...
  • webService详细

    千次阅读 多人点赞 2019-07-11 10:28:02
    webServiceWebService概述 1.1 WebService是什么 WebService是一种跨编程语言和跨操作系统平台的远程调用技术。 Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的...
  • WebService

    千次阅读 2018-11-12 17:16:42
    WebService 0. WebService简介 0.1 问题引入 问题一: Ø 它们公司服务器的数据库中都保存了天气预报数据吗? Ø 如果没有, 那数据都存在哪了呢? Ø 这些网站是如何得到这些数据的呢? 问题二: Ø 各个门户网站...
  • WebService基本介绍

    千次阅读 2018-03-05 15:18:56
    什么是WebService?W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计。Web Service服务通常被定义为一组模块化的API,它们可以通过网络进行调用,来执行远程系统的请求服务。...
  • Webservice工作原理及实例

    万次阅读 多人点赞 2016-04-04 23:12:08
    Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是:通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI...
  • webservice

    千次阅读 2011-11-11 09:35:32
    Web Services是由企业发布的完成其特定商务需求的在线应用服务,其他公司或应用软件能够通过Internet来...webservice 应用程序分支,是自包含、自描述、模块化的应用,可以发布、定位、通过web调用。Web Service是
  • 手把手教你如何玩转WebService(包含项目实践)

    万次阅读 多人点赞 2018-05-06 14:07:36
    情景引入: 时间:早晨 8 : 00 am 小白:起床起床,,,公司又来需求了,你还在睡觉,快点起来~! 我:大惊小怪,又怎么了呢?小白,别一惊一乍的,打扰我的美梦 小白:公司给了个新需求,你还记得,咱们上次做...
  • WebService客户端几种实现方式

    万次阅读 多人点赞 2018-09-09 17:54:11
    1。发布一个webservice服务。 2。jdk原生调用方式和import生成代码 3。cxf两种调用方式。 4。axis和axis2调用方式 5。httpClient调用方式。 httpclient4.5.2 httpmime4.5.2
  • WebService上传下载文件

    千次下载 热门讨论 2011-10-27 14:17:46
    webservice作为服务器端,以流的方式实现文件的上传和下载,可以自动调用winrar进行压缩和加密,支持多线程和断点续传功能,默认是16K一个包,全部源码,已经在实际项目中应用。客户端有winform和服务两种方式的...
  • java调用webservice接口 几种方法

    万次阅读 多人点赞 2017-03-15 15:31:28
    webservice的 发布一般都是使用WSDL(web service descriptive language)文件的样式来发布的,在WSDL文件里面,包含这个webservice暴露在外面可供使用的接口。今天搜索到了非常好的 webservice provider列表 ...
  • Android通过webservice连接Sqlserver实例

    千次下载 热门讨论 2012-12-02 10:08:27
    Android连接SQLServer详细教程(数据库+服务器+客户端) 博客http://blog.csdn.net/zhyl8157121/article/details/8169172中的资源
  • 浅谈SOAP Webservice和RESTful Webservice REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性。REST提出设计概念和准则为: 1.网络上的所有事物...
  • Java WebService接口生成和调用 图文详解

    万次阅读 多人点赞 2017-04-22 10:48:24
    webservice简介: Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或...
  • WebService接口开发详解(源码)

    万次阅读 2019-03-22 08:18:53
    业务场景:给一家公司的两个系统之间做部分数据做同步,A系统中进行业务操作后同步到B系统中,这样就不需要B系统再次进行...第一步,搭建WebService服务,建立WebService接口及实现类: /** * WebService接口 * ...
  • 一:WebService的服务端发布 1:发布web程序服务端发布 2:本地发布 二:Webservice客户端调用: 1:本地生成代码,直接调用: 2、利用dos命令生成代码,和第一种基本一致 3:利用apache的AXIS直接调用远程...
1 2 3 4 5 ... 20
收藏数 145,043
精华内容 58,017
关键字:

webservice