如何使用 SOAP UI 生成的代码进行 SOAP 调用?

How to Make a SOAP Call using SOAP UI Generated code?

我承认我对 SOAP 连接性的了解超出了我的理解范围。我使用 SOAP UI 从第三方给我的 wsdl 位置生成 Java 类。

这生成了一个界面:

@WebService(name = "Ext_Webservice_SoapPort", targetNamespace = "https://ws.185red.com")
@SOAPBinding(style = SOAPBinding.Style.RPC)
@XmlSeeAlso({ ObjectFactory.class })
public interface ExtWebserviceSoapPort
{
    @WebMethod(action = "https://ws.185red.com#acceptArrayOfInt")
    @WebResult(partName = "return")
    boolean acceptArrayOfInt(@WebParam(name = "param", partName = "param") final ArrayOfInt p0);
    
    @WebMethod(action = "https://ws.185red.com#acceptArrayOfStrings")
    @WebResult(partName = "return")
    boolean acceptArrayOfStrings(@WebParam(name = "param", partName = "param") final ArrayOfString p0);
    
    @WebMethod(action = "https://ws.185red.com#acceptArrayOfComplexType")
    @WebResult(partName = "return")
    boolean acceptArrayOfComplexType(@WebParam(name = "param", partName = "param") final ArrayOfExtWebserviceComplextypePerson p0);
    
    @WebMethod(action = "https://ws.185red.com#acceptComplexType")
    @WebResult(partName = "return")
    boolean acceptComplexType(@WebParam(name = "param", partName = "param") final ExtWebserviceComplexTypePerson p0);
    
    @WebMethod(action = "https://ws.185red.com#returnArrayOfInt")
    @WebResult(partName = "return")
    ArrayOfInt returnArrayOfInt();
    
    @WebMethod(action = "https://ws.185red.com#returnArrayOfStrings")
    @WebResult(partName = "return")
    ArrayOfString returnArrayOfStrings();
    
    @WebMethod(action = "https://ws.185red.com#returnArrayOfComplexType")
    @WebResult(partName = "return")
    ArrayOfExtWebserviceComplextypePerson returnArrayOfComplexType();
    
    @WebMethod(action = "https://ws.185red.com#returnComplexType")
    @WebResult(partName = "return")
    ExtWebserviceComplexTypePerson returnComplexType();
    
    @WebMethod(action = "https://ws.185red.com#login")
    @WebResult(partName = "return")
    String login(@WebParam(name = "username", partName = "username") final String p0, @WebParam(name = "password", partName = "password") final String p1);
    
    @WebMethod(action = "https://ws.185red.com#logout")
    @WebResult(partName = "return")
    boolean logout();
    
    @WebMethod(operationName = "FetchData", action = "https://ws.185red.com#FetchData")
    @WebResult(partName = "return")
    ArrayOfExtWebserviceComplextypeRecordwithoutkey fetchData(@WebParam(name = "formId", partName = "formId") final int p0, @WebParam(name = "criteria", partName = "criteria") final ArrayOfExtWebserviceComplextypeSearchcriteria p1, @WebParam(name = "keysToFetch", partName = "keysToFetch") final ArrayOfString p2);
    
    @WebMethod(operationName = "FetchDataCount", action = "https://ws.185red.com#FetchDataCount")
    @WebResult(partName = "return")
    int fetchDataCount(@WebParam(name = "formId", partName = "formId") final int p0, @WebParam(name = "criteria", partName = "criteria") final ArrayOfExtWebserviceComplextypeSearchcriteria p1);
    
    @WebMethod(operationName = "FetchRecordByUniqueKey", action = "https://ws.185red.com#FetchRecordByUniqueKey")
    @WebResult(partName = "return")
    ExtWebserviceComplexTypeRecordWithKey fetchRecordByUniqueKey(@WebParam(name = "formId", partName = "formId") final int p0, @WebParam(name = "uniqueKey", partName = "uniqueKey") final String p1, @WebParam(name = "tokensToFetch", partName = "tokensToFetch") final ArrayOfString p2);
    
    @WebMethod(operationName = "UpdateDateFulfillment", action = "https://ws.185red.com#UpdateDateFulfillment")
    @WebResult(partName = "return")
    ArrayOfExtWebserviceComplextypeUpdatedataresult updateDateFulfillment(@WebParam(name = "formId", partName = "formId") final int p0, @WebParam(name = "values", partName = "values") final ArrayOfExtWebserviceComplextypeRecordwithkey p1);
    
    @WebMethod(operationName = "UpdateData", action = "https://ws.185red.com#UpdateData")
    @WebResult(partName = "return")
    ArrayOfExtWebserviceComplextypeUpdatedataresult updateData(@WebParam(name = "formId", partName = "formId") final int p0, @WebParam(name = "values", partName = "values") final ArrayOfExtWebserviceComplextypeRecordwithkey p1, @WebParam(name = "markAsComplete", partName = "markAsComplete") final boolean p2, @WebParam(name = "prepopulate", partName = "prepopulate") final boolean p3);
    
    @WebMethod(operationName = "DeleteData", action = "https://ws.185red.com#DeleteData")
    @WebResult(partName = "return")
    int deleteData(@WebParam(name = "formId", partName = "formId") final int p0, @WebParam(name = "criteria", partName = "criteria") final ArrayOfExtWebserviceComplextypeSearchcriteria p1);
}

感觉这些方法好像都设置好了,只需要传入数据字段就可以调用了。但是我不确定具体该怎么做。

例如,我要调用的第一个方法是登录方法。我的理解是我只是设置用户名和密码并调用该方法。然后检查 return 字符串。像这样:

@WebMethod(action = "https://ws.185red.com#login")
    @WebResult(partName = "return")
    @RequestMapping("/getAllTest")
    public String login(@WebParam(name = "username", partName = "username") String username, @WebParam(name = "password", partName = "password") String password) {
        username = "";
        password = "";
        //webresult return?
        return "";
         
    } 

为了 A) 实际发送请求和 B) 查看响应,我还需要做些什么吗?我相信我应该只需要设置变量并且它应该全部设置。我知道我需要实际调用请求,但我不是通过设置 WebMethod/WebResult 注释并将其指向本地网页上的端点位置来实现的吗?

再次完全超出我的理解范围,如果有人能指出一些文档,我将非常感激。

提前致谢。

既然你说你不懂,那我就先介绍一下吧。

SOAP Web 服务只是一个 API 暴露在 Web 上,可以通过发送(然后接收)XML 消息作为有效负载使用 HTTP POST 方法调用。此 XML 消息必须具有特定格式,由 the SOAP protocol as well as the documentation of the web service, commonly also in machine readable format as a WSDL.

指定

您可以通过任何可用的方式自行构建这些消息(甚至字符串连接也可以),然后使用您喜欢的任何 HTTP 库发出 HTTP 请求。但是您随后还必须解析从 Web 服务收到的 XML 响应,以从中提取有用的值。这真是令人头疼。

因为 SOAP 是一个定义了规则的协议,而 WSDL 描述了 Web 服务契约,您可以使用 WSDL 生成客户端代码来为您处理这些事情。它将构建 XML 请求消息并解析 XML 响应消息,并将通过为您进行适当的 HTTP 调用来调用服务的操作。您将从客户那里得到的将是熟悉的 Java 对象和方法,您可以使用这些对象和方法而不用担心网络上发生的事情。

你是用 SoapUI 做的,但我不确定你从中得到了什么样的客户端代码。您正在显示一个界面,但这还不足以调用该服务。它只是定义了服务所有操作的契约。这些注释只是添加有关操作的元数据。他们不调用这些方法。为此,您需要一个合适的客户,而不仅仅是一份合同。

例如,您问题中显示的注释是 JAX-WS specification. You need a JAX-WS implementation of the client to handle the call to the service for you. Something like Apache CXF 的一部分。

我建议您不要使用 SoapUI 生成代码。使用您选择的实现从 WSDL 生成代码。例如,Apache CXF 有一个名为 wsdl2java 的命令行工具(也是 Maven 插件)可以为您生成客户端代码。然后就像任何 Java 对象一样,只需实例化生成的客户端并在其上调用方法即可。这些方法将接收 Java 个对象和 return java 个对象。与 SOAP 或 HTTP 请求相关的所有其他内容都由客户端为您处理。

例如:

wsdl2java -client -keep -d C:\temp http://www.dneonline.com/calculator.asmx?WSDL

将为该在线演示 Web 服务生成一堆 classes:http://www.dneonline.com/calculator.asmx?WSDL

Add.java
AddResponse.java
Calculator.java
CalculatorSoap.java
CalculatorSoap_CalculatorSoap12_Client.java
CalculatorSoap_CalculatorSoap_Client.java
Divide.java
DivideResponse.java
Multiply.java
MultiplyResponse.java
ObjectFactory.java
package-info.java
Subtract.java
SubtractResponse.java

这些文件包含一个客户端 class,里面有一个 main() 方法,显示了如何调用服务操作。例如:

private static final QName SERVICE_NAME = new QName("http://tempuri.org/", "Calculator");

public static void main(String args[]) throws java.lang.Exception {
    URL wsdlURL = Calculator.WSDL_LOCATION;
    
    // ...
    
    Calculator ss = new Calculator(wsdlURL, SERVICE_NAME);
    CalculatorSoap port = ss.getCalculatorSoap();

    // ...
    
    System.out.println("Invoking add...");
    int _add_intA = 0;
    int _add_intB = 0;
    int _add__return = port.add(_add_intA, _add_intB);
    System.out.println("add.result=" + _add__return);

    // ...
}

这些生成的 classes 从 Apache CXF 框架扩展 classes 并为您处理调用。

这个特定示例包含两个客户端 classes,因为我用来解释它的演示服务有两个绑定,分别用于 SOAP 1.1 和 SOAP 1.2。通过两个 SOAP 版本调用服务的客户端代码几乎相同,您只需要先 select 所需的端口。

希望这足以说明问题,以便您现在了解调用服务需要执行的操作。