一序
隨着技術的發展,之前的webservice已經被rpc跟restful json替代了。因爲業務需要,調用第三方的webservice接口。網上一搜,基本上都是10年前的文章了。而且好多人是遇到了問題,不知道怎麼解決。因爲問題多樣,僅供參考。
說這個話題暴露年齡了,網上看java調用的框架無非是:axis、axis2、cxf、xFire等,做服務端與客戶端都行,我們要做的事客戶端,所以儘量少去引用一堆jar.
二 問題 401
想嘗試使用httpClient來調用,帖子很多,不貼了。
報錯: HTTP/1.1 401 Unauthorized
我加上了授權的用戶名、密碼。
httpPost.addHeader(new BasicHeader("Authorization", "Basic " + Base64.getEncoder().encodeToString((username+":"+password).getBytes())));
這樣能解決校驗,因爲我的參數是自定義對象,所以我傳了json.
直接返回500.內部錯誤了。
所以我理解需要確定xml報文格式了。
三 AXis2
1RPC方式,不生成客戶端代碼,引入相應的axis2的jar包
2應用document方式調用 ,也就是org.apache.axis2.client.ServiceClient類進行遠程調用web服務,不生成客戶端
3用wsdl2java工具,生成客戶端方式調用webservice服務(不推薦啊)
下面是我的調試之路:
3.1 rpc
爲什麼我開始選擇這種方式呢?
因爲我要傳參,看上去相對簡單些:
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);
這個對比下來還是簡單些。但是調用接口提示:
<Status>102</Status><Message>接口異常:未將對象引用設置到對象的實例
雖然我已經設置了
options.setAction("http://WebXml.com.cn/XXaction");
就在這時,我發現了
<soap:operation soapAction="http://tempuri.org/XXaction" style="document"/>
這種方式搜了下,不支持RPC的。所以放棄了。
教訓:看這些webservice,不管你喜歡不喜歡,還是要去掃盲下基本概念的。因爲這個方法參數多,幾十個。一折通半天就過去了,而且對方是ASP。不是一個技術棧,沒有Java調用的demo.只有wsdl能看。
3.2 document
先看下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了。