随着技术的发展,之前的webservice已经被rpc跟restful json替代了。因为业务需要,调用第三方的webservice接口。网上一搜,基本上都是10年前的文章了。而且好多人是遇到了问题,不知道怎么解决。因为问题多样,仅供参考。
说这个话题暴露年龄了,网上看java调用的框架无非是:axis、axis2、cxf、xFire等,做服务端与客户端都行,我们要做的事客户端,所以尽量少去引用一堆jar.
想尝试使用httpClient来调用,帖子很多,不贴了。
报错: HTTP/1.1 401 Unauthorized
我加上了授权的用户名、密码。
httpPost.addHeader(new BasicHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((username+":"+password).getBytes())));
这样能解决校验,因为我的参数是自定义对象,所以我传了json.
直接返回500.内部错误了。
所以我理解需要确定xml报文格式了。
1RPC方式,不生成客户端代码,引入相应的axis2的jar包
2应用document方式调用 ,也就是org.apache.axis2.client.ServiceClient类进行远程调用web服务,不生成客户端
3用wsdl2java工具,生成客户端方式调用webservice服务(不推荐啊)
下面是我的调试之路:
为什么我开始选择这种方式呢?
因为我要传参,看上去相对简单些:
https://blog.csdn.net/menghuanzhiming/article/details/78489527?utm_source=blogkpcl4
这篇文章有详细的介绍:
贴一下我关注的点:
// 使用RPC方式调用WebService
RPCServiceClient serviceClient = new RPCServiceClient();
// 创建WSDL的URL,注意不是服务地址
String url = "http://hiepa.heliteq.com/WebServices/TestWebService.asmx?wsdl";
// 指定调用WebService的URL
EndpointReference targetEPR = new EndpointReference(url);
Options options = serviceClient.getOptions();
// 确定目标服务地址
options.setTo(targetEPR);
options.setAction("http://tempuri.org/Test");
// 指定方法的参数值
Object[] parameters = new Object[] {"parama", "paramb","paramc"};
// 创建服务名称
// 1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace)
// 2.localPart - 服务视图名
QName qname = new QName("http://WebXml.com.cn/", "XXaction");
// 调用方法一 传递参数,调用服务,获取服务返回结果集
OMElement element = serviceClient.invokeBlocking(qname, parameters);
这个对比下来还是简单些。但是调用接口提示:
虽然我已经设置了
options.setAction("http://WebXml.com.cn/XXaction");
就在这时,我发现了
这种方式搜了下,不支持RPC的。所以放弃了。
教训:看这些webservice,不管你喜欢不喜欢,还是要去扫盲下基本概念的。因为这个方法参数多,几十个。一折通半天就过去了,而且对方是ASP。不是一个技术栈,没有Java调用的demo.只有wsdl能看。
先看下wsdl文档:
网上也有很多文章,先看下官网:
public class TestClient {
private static EndpointReference targetEPR =
new EndpointReference(
"http://localhost:8080/axis2/services/SpringAwareService");
/**
* Simple axis2 client.
*
* @param args Main
*/
public static void main(String[] args) {
try {
OMFactory factory = OMAbstractFactory.getOMFactory();
OMNamespace omNs = factory.createOMNamespace(
"http://springExample.org/example1", "example1");
OMElement method = factory.createOMElement("getValue", omNs);
OMElement value = factory.createOMElement("Text", omNs);
value.addChild(factory.createOMText(value, "Some String "));
method.addChild(value);
ServiceClient serviceClient = new ServiceClient();
Options options = new Options();
serviceClient.setOptions(options);
options.setTo(targetEPR);
//Blocking invocation
OMElement result = serviceClient.sendReceive(method);
StringWriter writer = new StringWriter();
result.serialize(XMLOutputFactory.newInstance()
.createXMLStreamWriter(writer));
writer.flush();
System.out.println("Response: " + writer.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
关于传参数,遇到坑了,看上面的wsdl也知道,普通的String类型的,对方能收到,对于复合类型的SDSendOrder。接收不到。
网上看了下,OMElement和Java对象之间的转换。
public static OMElement object2OMElement(Object[] oArray,String type){
OMElement omElement=
BeanUtil.getOMElement(new QName("SDSendOrder"),oArray,new QName(type),false,null);
return omElement;
}
public static OMElement object2OMElement_pull(Object obj){
XMLStreamReader reader = BeanUtil.getPullParser(obj);
StreamWrapper parser = new StreamWrapper(reader);
OMXMLParserWrapper stAXOMBuilder = OMXMLBuilderFactory.createStAXOMBuilder(OMAbstractFactory.getOMFactory(), parser);
OMElement element = stAXOMBuilder.getDocumentElement();
return element;
}
还是不行,传JSON也不行。甚至尝试了jaxb的去传。
这里的经验是,要想快速调:最好借助于可视化工具:soapUI等。找到要发送的报文。
我折腾一下午,终于把这几十个参数报文拼上了,就是理解的歧义,文档上说的传数组,以为外面包一层SDSendOrder,实际上不要直接拼下面的属性就行。
找到报文了。再切回去httpclient.
也行了:状态:HTTP/1.1 200 OK
结果提示:无法连接到远程服务器,那就对方有调用三方服务器。这个需要人工协调了,不是程序的事了,成了一半了。
*******************
总结:
对接三方,这个真的有一些客观制约条件。尤其是非主流的技术栈,需要时间去探索下。
就是:如果你要使用axis2这种框架,那么得关注繁琐的webservice框架,要熟悉下基本概念。反过来:如果确认好报文,那么还是推荐httpclient.
回忆性网上google了前面的一堆文章,留言说:401 怎么办?未将对象引用设置到对象的实例 ?
还有类似的错误,都是很少有回答的,时间几年过去了,我觉得应该早就解决了。
我把我遇到的坑分享一下,如果对你有所帮助,就OK了。