記錄一次springboot工程調用webservice

一序

   隨着技術的發展,之前的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了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章