JWS(Java Web Service) 调用第三方 webService 服务·天气预报

目录

文档说明

wsimport 生成代理类

解析组件 's:schema' 时出错

解决办法

客户端调用


文档说明

1、《WebService 常用免费调用接口》中提供了生活中常见的一些 webService 服务,而且这些服务都是免费的,大家都可以调用,本文将选取里面的 "中国气象局" 天气查询服务作为调用演示。

Endpoint 地址:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

WSDL地址:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl

wsimport 生成代理类

1、已经知道 Java 开发时,使用自带的 wsimport.exe 工具即可根据服务端提供的 WSDL 文件生成客户端代理类,所以第一步就是根据上面的 WSDL 地址生成客户端使用的代理类。

解析组件 's:schema' 时出错

PS E:\wmx\webservice> wsimport -keep -d E:\wmx\webservice -verbose http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
正在解析 WSDL...
[WARNING] src-resolve.4.2: 解析组件 's:schema' 时出错。在该组件中检测到 's:schema' 位于名称空间 'http://www.w3.org/2001/XMLSchema' 中, 但无法从方案文档 'http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl#types?schema1' 引用此名称空间的组件。如果这是不正确的名称空间, 则很可能需要更改 's:schema' 的前缀。如果这是正确的名称空间, 则应将适当的 'import' 标记添加到 'http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl#types?schema1'。
  http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl#types?schema1的第 44 行
[WARNING] src-resolve: 无法将名称 's:schema' 解析为 'element declaration' 组件。
  http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl#types?schema1的第 44 行
[ERROR] undefined element declaration 's:schema'
  http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl的第 44 行
[ERROR] undefined element declaration 's:schema'
  http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl的第 85 行
Exception in thread "main" com.sun.tools.internal.ws.wscompile.AbortException
        at com.sun.tools.internal.ws.processor.modeler.wsdl.JAXBModelBuilder.bind(JAXBModelBuilder.java:129)
        at com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModeler.buildJAXBModel(WSDLModeler.java:2283)
        at com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModeler.internalBuildModel(WSDLModeler.java:183)
        at com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModeler.buildModel(WSDLModeler.java:126)
        at com.sun.tools.internal.ws.wscompile.WsimportTool.buildWsdlModel(WsimportTool.java:429)
        at com.sun.tools.internal.ws.wscompile.WsimportTool.run(WsimportTool.java:190)
        at com.sun.tools.internal.ws.wscompile.WsimportTool.run(WsimportTool.java:168)
        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 com.sun.tools.internal.ws.Invoker.invoke(Invoker.java:159)
        at com.sun.tools.internal.ws.WsImport.main(WsImport.java:42)
PS E:\wmx\webservice>

2、如上所示生成时出错,执行失败,出现的原因是 webService 服务端如果是 .net 写的,则使用 Java wsimport.exe 生成时就会报错

3、开发中如果没有遇到这个错误,自然是最好,万一遇到,则可以一试,亲测有效。

解决办法

1、针对 .net 开发的 webService 服务端,Java wsimport.exe 生成代理类出错解决办法如下:

1)将服务端的 wsdl 文档保存到本地,如 E:\wmx\webservice\weather.wsdl.xml、E:\wmx\webservice\weather.wsdl、E:\wmx\webservice\weather.xml (经实测文件的后缀名其实关系不大,都可以正常生成)

2、修改 wsdl 文档以下内容:
将文件中所有的 <s:element ref="s:schema" /><s:any /> 替换成 <s:any minOccurs="2" maxOccurs="2"/>

2、直接在 wsdl 文档页面右键,选择查看源代码,然后将 Ctrl + S 保存即可,然后便可打开文件,替换其中的内容:

3、此时使用 wsimport.exe 再次生成,便可以正确执行:

客户端调用

1、显然这种别人写的服务端,不用多想,将生成的 .java 文件全部导入即可,然后需要找到里面的服务接口,可以凭直觉,也可以从 wsdl 文档中的 <service> 元素中查找

2、通常情况下,从 wsdl 的 Url 地址中也是可以找到的,如本例的 :http://www.webxml.com.cn/WebServices/Weath
erWebService.asmx?wsdl,就是其中的 "WeatherWebService"

3、将生成好的 .java 文件导入到项目中:

特别提醒:

1)代理类中有些类相互引用时,使用的是绝对地址,如在 WeatherWebServiceSoap 接口中使用了这样的代码, cn.com.webxml.ArrayOfString 来引用 ArrayOfString ,于是要不就是自己新建和它一样的包,然后放置进去,如上所示,要不就是修改源码中原来的包名和自己包名的保持一致,否则报错。

2)因为 wsimport.exe 是转换的本地的 wsdl 文件,而不是在线的 wsdl 文件,所以代码中关联的也是本地的 wsdl 文件,这个文件必须存在,如果这个文件删除了,则项目运行的时候就会找不到而解析失败。所以如果文件移动了位置,则代码中也要相应的修改。

3)建议将 wsdl 文件放在项目中(资源目录下),这样就可以和项目一起移动,否则如果将来项目移动了,而忘了本地的 wsdl 文件,显然运行就报错了。

4、调用测试类代码如下,这是我们自己唯一要写的代码(如果上面没有移动 wsdl文件到项目中内部的话),几行即可搞定:

import cn.com.webxml.ArrayOfString;
import cn.com.webxml.WeatherWebService;
import cn.com.webxml.WeatherWebServiceSoap;

import java.util.List;
import java.util.logging.Logger;

/**
 * Created by Administrator on 2019/1/25 0025.
 */
public class Web_service {
    //日志记录器
    public static final Logger logger = Logger.getGlobal();

    public static void main(String[] args) {
        /**1、创建实现类对象
         * */
        WeatherWebService weatherWebService = new WeatherWebService();
        /** 2、获取服务接口实例
         * 这些代码只能看着源码跟着感觉来写,因为代码完全是人家写的,对方通常也不会提供什么使用文档的
         */
        WeatherWebServiceSoap weatherWebServiceSoap = weatherWebService.getWeatherWebServiceSoap();
        /**
         *3、有了服务接口实例,就可以调用其中的方法了,这里返回值也是对方使用的对象
         */
        ArrayOfString arrayOfString = weatherWebServiceSoap.getWeatherbyCityName("长沙");
        /**
         * 4、看着源码即可轻松写出,毕竟都是程序猿,猜也猜出它的目的
         */
        List<String> stringList = arrayOfString.getString();
        int count = 1;
        for (String s : stringList) {
            System.out.println((count++) + ":::" + s);
        }
    }
}

5、运行结果如下:

如上所示,获取数据成功,有了数据,至于怎么使用,就是自己的事情了,根据业务需求使用即可。

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/87370571