0 背景
工作中,要调用客户的WebService服务,遇到了很多奇奇怪怪的问题,在这里记录一下都是怎么解决的。网上关于这方面的博文不少,但本着学习--总结的习惯,决定出炉一篇自己在学习过程中的理解、遇到的问题和解决的方法。推荐我看过觉得不错的一篇 WebService详解,内容基础且全面。而本文从工程角度出发,偏向应用。
1 简介
这里主要采用Axis,相关包的gradle下载方式如下:
// https://mvnrepository.com/artifact/org.apache.axis/axis
compile group: 'org.apache.axis', name: 'axis', version: '1.4'
// https://mvnrepository.com/artifact/axis/axis-ant
compile group: 'axis', name: 'axis-ant', version: '1.4'
// https://mvnrepository.com/artifact/javax.xml.rpc/javax.xml.rpc-api
compile group: 'javax.xml.rpc', name: 'javax.xml.rpc-api', version: '1.1.2'
// https://mvnrepository.com/artifact/axis/axis-jaxrpc
compile group: 'axis', name: 'axis-jaxrpc', version: '1.3'
// https://mvnrepository.com/artifact/activation/activation
compile group: 'activation', name: 'activation', version: '1.0.2'
// https://mvnrepository.com/artifact/commons-discovery/commons-discovery
compile group: 'commons-discovery', name: 'commons-discovery', version: '0.5'
// https://mvnrepository.com/artifact/commons-logging/commons-logging
compile group: 'commons-logging', name: 'commons-logging', version: '1.1.1'
// https://mvnrepository.com/artifact/wsdl4j/wsdl4j
compile group: 'wsdl4j', name: 'wsdl4j', version: '1.6.2'
// https://mvnrepository.com/artifact/javax.xml.soap/javax.xml.soap-api
compile group: 'javax.xml.soap', name: 'javax.xml.soap-api', version: '1.4.0'
// https://mvnrepository.com/artifact/javax.mail/mailapi
compile group: 'javax.mail', name: 'mailapi', version: '1.4.3'
在开发初始并不知道要引入这么多相关包,因此带来各种各样的编译错误;采用上述方式引入包之后,不再有编译错误;如果再报错(比如call.invoke的 NullPointerException 异常),请认真核对自己的url、namespace和调用方法名的一致性和正确性。 (后面会详述报错内容和解决方法)
2 调用WebService服务的三种方法
根据WebService提供的URL(直接在浏览器访问)可以生成wsdl文件,文件中包含WebService服务对外提供的接口。可结合百度了解wsdl文件参数含义(这里不详述)。
第一种:通过axis将WebService提供的wsdl文件生成对应的java类,这样相当于调用本地类一样调用WebService服务(本地需要java环境),但是因为生成的代码量太大,看着就不美观,个人不太喜欢。
使用命令:wsimport -encoding utf8 -keep -p com.haiyisoft -Xnocompile http://ip:port/services/xxx?wsdl
命令解释: wsimport 命令
-encoding 指定生成代码的编码格式
-keep 保存生成的代码
-p 指定包名
-Xnocompile 表示生成的代码不编译
编写调用代码部分,自己去看看类和接口的定义就知道啦
第二种:采用RPC方式调用(墙推)
采用RPC方式就很简单了,只需自己写一个调用类就可以实现,这里贴出一个调用代码:
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.rpc.ParameterMode;
import org.apache.axis.encoding.XMLType;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;
/**
* @author wy
* @description rpc调用webservice
* @date 2019/8/30 18:56
*/
public class CallUtil {
public static String doPost(String url, byte[] imgFileBytes, String userKey,String namespaceURl,String localPart) {
Service service = new Service();
Call call;
try {
call = (Call) service.createCall();
call.setTargetEndpointAddress(new URL(url));
//namespaceURl是命名空间,localPart是调用的方法
call.setOperationName(new QName(namespaceURl, localPart));
call.addParameter("imgFileBytes", XMLType.SOAP_BASE64BINARY, ParameterMode.IN);
call.addParameter("key", XMLType.SOAP_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
call.setTimeout(30000);
System.out.println("params: "+imgFileBytes.length+" "+userKey);
//imgFileBytes和userKey是要上传的参数
resultString = (String) call.invoke(new Object[]{imgFileBytes,userKey});
} catch (ServiceException e) {
System.out.println("createCall Exception: ");
e.printStackTrace();
} catch (RemoteException e) {
System.out.println("invoke Exception: ");
e.printStackTrace();
} catch (MalformedURLException e) {
System.out.println("newUrl Exception: ");
e.printStackTrace();
}
return resultString;
}
}
第三种:采用RestTemplate,实际是HttpUrlConnection调用,这个没有实现,就不多说啦
3 遇到的问题和解决的方法(我采用RPC方式调用)
期间遇到的问题真的多多多啊,下面贴出来几个看看是怎么解决的。
1、NoClassDefFoundError:could not initialize class org.apache.axis.client.AxisClient 显然是编译错误,但是一开始没有想到是缺少包,有点经验不足。网上多番探查后,才知道是缺少包导致的。引入commons-discovery 和 commons-logging包,因为前者依赖后者,因此都需引入。
2、call.invoke导致的NullPointerException(两个错误同时出现), 这个问题可真是困扰了我一两天。call.invoke报错,排查一下也就几个原因:比如上传参数格式错误、比如调用方法错误。 因为跟客户那边不好沟通,所以耽搁了一天的时间,后来终于解决了,最终的bug定位说起来简直好笑!是url和命名空间、方法名不匹配。也就是我用的url不是调用这个方法的。。已跪!!
因为是客户的WebService服务,保密起见抹了一下下,但不影响看报错。
好啦!主要内容大概就到这里了,其他的错误不太好意思拿出手......