2013-04-11 61 views
97

我對Web服務世界相對陌生,我的研究似乎讓我困惑得比開導我多,我的問題是我得到了一個庫(jar),我必須使用一些web服務功能來擴展它。如何從Java類執行SOAP Web服務調用?

這個庫將被其他開發者共享,並且在jar中的類中將會有一些類,這些類有一個調用webservice的方法(基本上設置類的屬性,做一些業務邏輯,比如存儲對象在一個數據庫等,併發送對象與這些修改)。我希望儘可能簡單地調用此服務,希望儘可能簡單,以便使用該類的開發人員只需要這樣做。

Car c = new Car("Blue"); 
c.webmethod(); 

我一直在研究JAX-WS服務器上使用,但在我看來,我不需要在服務器中創建一個wsimport,也不在客戶端上wsimport,因爲我知道,無論有類,我只需要在服務器和客戶端共享的類之間進行一些交互。您認爲在課堂上進行web服務和調用有意義嗎?

+0

你的問題有點不清楚。你想創建的方法將(1)從Web服務獲取對象; (2)與對象一起工作;和(3)將其發回Web服務。是嗎? – acdcjunior 2013-04-11 03:36:28

+0

不,對象將在客戶端創建,它將被髮送到調用中的ws,ws將設置一個變量,例如currentTime,執行一些業務邏輯,如將其存儲在數據庫中,然後發送給將對象返回給客戶端並設置currentTime。希望我能更好地解釋我的自我。謝謝。 – jpz 2013-04-11 04:57:09

回答

222

我理解你的問題歸結爲如何從Java調用SOAP(JAX-WS)Web服務並獲取其返回對象。在這種情況下,您有兩種可能的方法:

  1. 通過wsimport生成Java類並使用它們;或
  2. 創建SOAP客戶端:
    1. 序列化服務的參數,以XML;
    2. 通過HTTP操作調用Web方法;和
    3. 將返回的XML響應解析回對象。


關於(採​​用wsimport)第一種方法:

我看你已經有服務(實體或其他)業務類,這是一個事實,即wsimport產生一整套新的類(它們與你已有的類重複)。

我很害怕,但是,在這種情況下,你只能之一:

  • 適應(編輯)wsimport生成的代碼,以使它使用業務類(這是困難的,有點不值得 - 每當WSDL發生變化時記住,你必須重新生成並重新調整代碼);或
  • 放棄並使用wsimport生成的類。 (在此解決方案中,您的業務代碼可以將生成的類作爲另一個架構層的服務使用。)

關於第二個方法(創建自定義的SOAP客戶端):

爲了實現第二種方法,你必須:

  1. 請來電:
    • 使用SAAJ(SOAP with Attachments API for Java)框架(見下文,它隨Java SE 1.6或更高版本提供)進行調用;或
    • 您也可以通過java.net.HttpUrlconnection(和一些java.io處理)來完成。
  2. 轉動物體進入和回程從XML:
    • 使用OXM(對象到XML映射)框架,例如JAXB序列化/反序列化從XML /成對象
    • 或者,如果您必須手動創建/解析XML(如果接收的對象與發送的對象只有一點差異,這可能是最好的解決方案)。

創建使用經典java.net.HttpUrlConnection SOAP客戶端並不難(但不是簡單其一),你可以在this link一個很好的起點代碼中找到。

我建議你使用SAAJ框架:

SOAP用於Java(SAAJ)附件API主要用於直接與發生在幕後的任何Web服務的SOAP請求/響應消息處理API。它允許開發人員直接發送和接收SOAP消息,而不是使用JAX-WS。

請參閱下面的使用SAAJ的SOAP Web服務調用的工作示例(運行它!)。它叫this web service

import javax.xml.soap.*; 

public class SOAPClientSAAJ { 

    // SAAJ - SOAP Client Testing 
    public static void main(String args[]) { 
     /* 
      The example below requests from the Web Service at: 
      https://www.w3schools.com/xml/tempconvert.asmx?op=CelsiusToFahrenheit 


      To call other WS, change the parameters below, which are: 
      - the SOAP Endpoint URL (that is, where the service is responding from) 
      - the SOAP Action 

      Also change the contents of the method createSoapEnvelope() in this class. It constructs 
      the inner part of the SOAP envelope that is actually sent. 
     */ 
     String soapEndpointUrl = "https://www.w3schools.com/xml/tempconvert.asmx"; 
     String soapAction = "https://www.w3schools.com/xml/CelsiusToFahrenheit"; 

     callSoapWebService(soapEndpointUrl, soapAction); 
    } 

    private static void createSoapEnvelope(SOAPMessage soapMessage) throws SOAPException { 
     SOAPPart soapPart = soapMessage.getSOAPPart(); 

     String myNamespace = "myNamespace"; 
     String myNamespaceURI = "https://www.w3schools.com/xml/"; 

     // SOAP Envelope 
     SOAPEnvelope envelope = soapPart.getEnvelope(); 
     envelope.addNamespaceDeclaration(myNamespace, myNamespaceURI); 

      /* 
      Constructed SOAP Request Message: 
      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:myNamespace="https://www.w3schools.com/xml/"> 
       <SOAP-ENV:Header/> 
       <SOAP-ENV:Body> 
        <myNamespace:CelsiusToFahrenheit> 
         <myNamespace:Celsius>100</myNamespace:Celsius> 
        </myNamespace:CelsiusToFahrenheit> 
       </SOAP-ENV:Body> 
      </SOAP-ENV:Envelope> 
      */ 

     // SOAP Body 
     SOAPBody soapBody = envelope.getBody(); 
     SOAPElement soapBodyElem = soapBody.addChildElement("CelsiusToFahrenheit", myNamespace); 
     SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("Celsius", myNamespace); 
     soapBodyElem1.addTextNode("100"); 
    } 

    private static void callSoapWebService(String soapEndpointUrl, String soapAction) { 
     try { 
      // Create SOAP Connection 
      SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); 
      SOAPConnection soapConnection = soapConnectionFactory.createConnection(); 

      // Send SOAP Message to SOAP Server 
      SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(soapAction), soapEndpointUrl); 

      // Print the SOAP Response 
      System.out.println("Response SOAP Message:"); 
      soapResponse.writeTo(System.out); 
      System.out.println(); 

      soapConnection.close(); 
     } catch (Exception e) { 
      System.err.println("\nError occurred while sending SOAP Request to Server!\nMake sure you have the correct endpoint URL and SOAPAction!\n"); 
      e.printStackTrace(); 
     } 
    } 

    private static SOAPMessage createSOAPRequest(String soapAction) throws Exception { 
     MessageFactory messageFactory = MessageFactory.newInstance(); 
     SOAPMessage soapMessage = messageFactory.createMessage(); 

     createSoapEnvelope(soapMessage); 

     MimeHeaders headers = soapMessage.getMimeHeaders(); 
     headers.addHeader("SOAPAction", soapAction); 

     soapMessage.saveChanges(); 

     /* Print the request message, just for debugging purposes */ 
     System.out.println("Request SOAP Message:"); 
     soapMessage.writeTo(System.out); 
     System.out.println("\n"); 

     return soapMessage; 
    } 

} 

關於使用JAXB進行序列化/反序列化,很容易找到關於它的信息。你可以從這裏開始:http://www.mkyong.com/java/jaxb-hello-world-example/

+0

如何使用上述方法設置肥皂版本? – Redone 2016-10-27 10:37:12

+0

我能夠使用你的方法,並且它在我使用你的URI的時候起作用,但是對於我自己的SOAP請求,我得到了一個響應,其中沒有顯示任何值,即''''。正如你所看到的,元素是關閉的,並且沒有信息從WS生成。 – santafebound 2016-11-08 14:45:34

+0

'GetInfoByCity'是'503Service Unavailable',它看起來像。 :( – 2017-08-11 20:44:47

1

或者只是使用Apache CXF's wsdl2java來生成可以使用的對象。

它包含在二進制包中,您可以從他們的網站下載。你可以簡單地運行這樣的命令:

$ ./wsdl2java -p com.mynamespace.for.the.api.objects -autoNameResolution http://www.someurl.com/DefaultWebService?wsdl 

它使用WSDL生成對象,你可以使用這樣的(對象名稱也從WSDL抓起,讓你的將是不同的一點):

DefaultWebService defaultWebService = new DefaultWebService(); 
String res = defaultWebService.getDefaultWebServiceHttpSoap11Endpoint().login("webservice","dadsadasdasd"); 
System.out.println(res); 

甚至有一個Maven插件生成來源:https://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html