1. 程式人生 > >Call調用webservice接口,使用命名空間和不使用命名空間的區別

Call調用webservice接口,使用命名空間和不使用命名空間的區別

.cn 測試 inf targe abs 註釋 命名空間 all 方式

  生活中我們會遇到許許多多的奇葩問題,而這些問題又是我們不得不解決的。

  我先用一段代碼來引出我想要說的內容:

import javax.jws.WebMethod;
import javax.jws.WebService;

/**
 * Created by 30721 on 2018/9/28.
 */
@WebService
public interface WstwoInter {

    @WebMethod
    String getInfo(String xml);
}
import cn.cy.webservice.inter.WstwoInter;
import org.springframework.stereotype.Component;

/** * Created by 30721 on 2018/9/28. */ @Component public class WstwoImpl implements WstwoInter { @Override public String getInfo(String xml) { System.out.println(xml); return xml; } }

而如果用org.apache.axis.client.Call類來調用就要這樣寫:

public static void main(String[] args) {
        
try { String url = "http://127.0.0.1:8002/cxf/service/webtwo?wsdl"; Service service = new Service(); Call call = (Call) service.createCall(); call.setTargetEndpointAddress(url); QName qName = new QName("http://inter.webservice.cy.cn/", "getInfo"); call.setOperationName(qName);
// WSDL裏面描述的接口名稱 QName qname = new QName("arg0"); call.addParameter(qname, XMLType.XSD_STRING, ParameterMode.IN);// 接口的參數 call.setReturnType(XMLType.XSD_STRING);// 設置返回類型 String temp = "測試人員"; String result = (String) call.invoke(new Object[] { temp }); // 給方法傳遞參數,並且調用方法 System.out.println("result is " + result); } catch (Exception e) { e.printStackTrace(); } }
描述wsdl中的方法需要帶上命名空間(我這邊的webservice的命名空間為:http://inter.webservice.cy.cn/)

技術分享圖片

如果使用技術分享圖片則會報如下的錯誤:

技術分享圖片
org.apache.axis.AxisFault: Unexpected wrapper element getInfo found.   Expected {http://inter.webservice.cy.cn/}getInfo.
    at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222)
    at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129)
    at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1776)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2964)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:118)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:504)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
    at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
    at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
    at org.apache.axis.Message.getSOAPEnvelope(Message.java:435)
    at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:796)
    at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
    at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
    at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
    at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
    at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
    at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
    at org.apache.axis.client.Call.invoke(Call.java:2767)
    at org.apache.axis.client.Call.invoke(Call.java:2443)
    at org.apache.axis.client.Call.invoke(Call.java:2366)
    at org.apache.axis.client.Call.invoke(Call.java:1812)
    at cn.cy.core.Main.main(Main.java:31)
AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Client
 faultSubcode: 
 faultString: Unexpected wrapper element getInfo found.   Expected {http://inter.webservice.cy.cn/}getInfo.
 faultActor: 
 faultNode: 
 faultDetail: 
    {http://xml.apache.org/axis/}stackTrace:Unexpected wrapper element getInfo found.   Expected {http://inter.webservice.cy.cn/}getInfo.
    at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222)
    at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129)
    at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1776)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2964)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:118)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:504)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
    at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
    at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
    at org.apache.axis.Message.getSOAPEnvelope(Message.java:435)
    at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:796)
    at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
    at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
    at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
    at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
    at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
    at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
    at org.apache.axis.client.Call.invoke(Call.java:2767)
    at org.apache.axis.client.Call.invoke(Call.java:2443)
    at org.apache.axis.client.Call.invoke(Call.java:2366)
    at org.apache.axis.client.Call.invoke(Call.java:1812)
    at cn.cy.core.Main.main(Main.java:31)

    {http://xml.apache.org/axis/}hostname:DESKTOP-MPUGA9U

Unexpected wrapper element getInfo found.   Expected {http://inter.webservice.cy.cn/}getInfo.
    at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222)
    at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129)
    at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1776)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2964)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:118)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:504)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
    at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
    at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
    at org.apache.axis.Message.getSOAPEnvelope(Message.java:435)
    at org.apache.axis.transport.http.HTTPSender.readFromSocket(HTTPSender.java:796)
    at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
    at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
    at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
    at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
    at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
    at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
    at org.apache.axis.client.Call.invoke(Call.java:2767)
    at org.apache.axis.client.Call.invoke(Call.java:2443)
    at org.apache.axis.client.Call.invoke(Call.java:2366)
    at org.apache.axis.client.Call.invoke(Call.java:1812)
    at cn.cy.core.Main.main(Main.java:31)
View Code

正常情況下接口交接都是服務端的服務寫好了,然後客戶端是直接根據寫好的服務進行調用測試,然而我並非這樣子的,與我交接的公司的接口平臺是現成的,而且是老系統沒有源碼無法做修改

這就很尷尬了,沒辦法只能服務端代碼改了,不過工作量不大還好,他們發編譯老系統的代碼後給我發了一段這樣的客戶端代碼:

技術分享圖片
String url = "http://127.0.0.1:8002/cxf/service/webtwo?wsdl";
            Service service = new Service();
            Call call = (Call) service.createCall();
            call.setTargetEndpointAddress(url);
            QName qName = new QName("http://inter.webservice.cy.cn/", "getInfo");
            call.setOperationName(qName);// WSDL裏面描述的接口名稱
            QName qname = new QName("http://inter.webservice.cy.cn/", "arg0");
            call.addParameter(qname, XMLType.XSD_STRING, ParameterMode.IN);// 接口的參數
            call.setReturnType(XMLType.XSD_STRING);// 設置返回類型
            String temp = "測試人員";
            String result = (String) call.invoke(new Object[] { temp });              // 給方法傳遞參數,並且調用方法
            System.out.println("result is " + result);
View Code

我看了一下代碼發現與上面代碼的區別就是參數那邊也要帶上命名空間地址。那麽服務端的接口就需要這樣改:
技術分享圖片
@WebService(targetNamespace="http://inter.webservice.cy.cn/")
public interface WstwoInter {

    @WebMethod
    String getInfo(@WebParam(targetNamespace="http://inter.webservice.cy.cn/") String xml);
}
View Code

這都是小問題,但是大問題出現了,服務發上去他們還是調用不到,發現還少了一個參數call.setUseSOAPAction(true);call.setSOAPActionURI(actionURI);這個參數者對應著@WebMethod(action=actionURI)
這個註釋。代碼:
技術分享圖片
@WebService(targetNamespace="http://inter.webservice.cy.cn/")
public interface WstwoInter {

    @WebMethod(action="getInfo")
    String getInfo(@WebParam(targetNamespace="http://inter.webservice.cy.cn/") String xml);
}
View Code

但是問題並非出在這個註釋,而是出在老系統調用這個actionURI的時候竟然是帶IP的,這樣就讓服務端的代碼移植性變的非常差。測試環境和生產環境必然是兩個不同的服務器不同的IP,不可能每次都修改代碼上的註解

@WebMethod(action="http://ip/xxx")ip,不現實。這時他們又說了接口平臺的另一個調用方式。不使用命名空間。代碼如下:
技術分享圖片
public static void main(String[] args) {
        try {
            String url = "http://127.0.0.1:8002/cxf/service/webtwo?wsdl";
            Service service = new Service();
            Call call = (Call) service.createCall();
            call.setUseSOAPAction(true);
            call.setTargetEndpointAddress(url);
            QName qName = new QName("getInfo");
            call.setOperationName(qName);// WSDL裏面描述的接口名稱
            QName qname = new QName("arg0");
            call.addParameter(qname, XMLType.XSD_STRING, ParameterMode.IN);// 接口的參數
            call.setSOAPActionURI("getInfo");
            call.setReturnType(XMLType.XSD_STRING);// 設置返回類型
            String temp = "測試人員";
            String result = (String) call.invoke(new Object[] { temp });              // 給方法傳遞參數,並且調用方法
            System.out.println("result is " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
View Code

這段代碼少了命名空間,多了一個actionURI,但是這個URI跟上面的不同,這個URI帶的是方法名,沒辦法,他們改不了,只能我們服務端來改了。我這樣子改:
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC, use = SOAPBinding.Use.ENCODED)
public interface WstwoInter {

    @WebMethod(action="getInfo")
    String getInfo(String xml);
}

終於接口跟他們調通了。

如果想深入理解@SOAPBinding這個註解,可參考https://blog.csdn.net/comman1999/article/details/1967907。


Call調用webservice接口,使用命名空間和不使用命名空間的區別