Java调用WebService服务总结

 

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服务,保密起见抹了一下下,但不影响看报错。

 

       好啦!主要内容大概就到这里了,其他的错误不太好意思拿出手......

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值