Java对接webservice踩坑记

1,480 阅读3分钟

背景:接公司一业务,对方只提供了一个wsdl文件/接口,无文档对接


了解webservice

Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。 Web Service技术, 能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件, 就可相互交换数据或集成。依据Web Service规范实施的应用之间, 无论它们所使用的语言、 平台或内部协议是什么, 都可以相互交换数据。Web Service是自描述、 自包含的可用网络模块, 可以执行具体的业务功能。

特点:

  • 解耦
  • 不限开发语言,协议
  • 单体架构协同

Java开发步骤

服务端开发

搭建服务端server流程,一般是开发接口,发布wsdl文件或者接口。 http://localhost:8081/test/api?wsdl 这个wsdl文件就是服务端提供的相关接口描述

客户端解析

但是作为使用者,我们要做的就是使用客户端去解析wsdl接口文件,进行调用。 网上找了一大堆,基本有两种方式去构建客户端:

  1. 代理调用
package com.it.client;

import com.it.interceptor.ClientLoginInterceptor;
import com.it.service.MessageService;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class CXFProxyClient {
    private static final String ADDRESS = "http://localhost:8080/services/MessageService?wsdl"// WebService服务地址

    public static void main(String[] args) {
        JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
        jaxWsProxyFactoryBean.setAddress(ADDRESS);
        jaxWsProxyFactoryBean.setServiceClass(MessageService.class);
        jaxWsProxyFactoryBean.getOutInterceptors().add(
                new ClientLoginInterceptor("admin","123456"// 设置用户名,密码
        );
        MessageService messageService = (MessageService)jaxWsProxyFactoryBean.create();
        String echo = messageService.echo("[webservice proxy invoke]");
        System.out.println("echo = " + echo);
    }

}
  1. 动态调用
package com.it.client;

import com.it.interceptor.ClientLoginInterceptor;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

public class CXFDynamicClient {
    private static final String ADDRESS = "http://localhost:8080/services/MessageService?wsdl"; // WebService服务地址

    public static void main(String[] args) throws Exception {
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient(ADDRESS);
        client.getOutInterceptors().add(new ClientLoginInterceptor("admin","123456"));
        String message = "dynamic";
        Object[] result = client.invoke("echo", message);
        System.out.println(result);
    }
}

盘点踩坑

使用jdk自带工具解析失败

这是用到的命令

PS D:\Program Files\Java\jdk1.8.0_202\bin> .\wsimport -d D:\code\webserve -keep -verbose -Xauthfile D:\code\webserve\aaa\11.txt http://xxxx.xxxx.xxxx:8000/sap/bc/srt/wsdl/flv_xxxxxxxx1/xxxxxx/xxx/xxxxx/sap/zfi_fun_012/800/zfi_fun_012/zfi_fun_012?sap-client=800?WSDL
正在解析 WSDL...

[ERRORServer returned HTTP response code: 401 for URLhttp://xxxxx.xxxxx.xxxx:8000/sap/bc/zfi_fun_012/800/zfi_fun_012/xxxxxxx?sap-client=800?WSDL,  "http://xxxxx.xxxxx.xxxx/zfi_fun_012/800/zfi_fun_012/zfi_fun_012?sap-client=800?WSDL" 需要授权, 请在C:\Users\Administrator.metro\auth中提供具有读取访问权限的授权文件, 或者使用 -Xauthfile 指定授权文件并在每一行上使用以下格式提供授权信息: http[s]://user:password@host:port//<url-path>
Exception in thread "main" com.sun.tools.internal.ws.wscompile.AbortException
        at com.sun.tools.internal.ws.wsdl.parser.MetadataFinder$WSEntityResolver.resolveEntity(MetadataFinder.java:187)
        at com.sun.tools.internal.ws.wsdl.parser.DOMForest.parse(DOMForest.java:198)
        at com.sun.tools.internal.ws.wsdl.parser.DOMForest.parse(DOMForest.java:134)
        at com.sun.tools.internal.ws.wsdl.parser.MetadataFinder.parseWSDL(MetadataFinder.java:96)
        at com.sun.tools.internal.ws.wscompile.WsimportTool.buildWsdlModel(WsimportTool.java:424)
        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)

由于对方地址server加了密,使用JDK自带工具wsimport,老是提示使用-Xauthfile,这个我也加了,还是报错,此路不通,如果对方server没有加密,此方法可以试试。

使用Idea解析

由于这个webservice是上古技术,所以越新的idea 对其支持的力度越小,这个对应的入库隐藏的越深,比较恶心。这里以IntelliJ IDEA 2021.3.3 (Ultimate Edition) 为例子。 按照网上说的,在这个里面找到webservice的入口,找不到网上说的webservice入口,一顿操作,按时下班。 正确姿势:

  1. 新建java项目,一路ok即可
  2. 添加框架
  3. 看到熟悉的东西了,一顿卡卡点

点击ok

由于 accessExternalSchema 属性设置的限制而不允许 'file' 访问, 因此无法读取方案文档 '***.xsd'

芭比q了,又报错???

快请如来佛祖!!!

jdk1.8版本兼容问题

速切1.6版本

快乐这不就来了

小结

这玩意,狗都不用。


参考文档 SpringBoot整合WebService

鸣谢@涛儿