添加 header 到 SOAP 服务客户端

Add header to SOAP service client

我需要与 SOAP 服务交换数据。该服务提供了许多 WSDL 端点,因此我使用其中之一来生成 Java 代码(我遵循了本教程:https://www.baeldung.com/maven-wsdl-stubs)。生成了许多 类 以及一个接口和一个服务。考虑这段代码:

代码服务接口:

package my.package.soapconsumer.models.service.getCodes;

import org.springframework.web.bind.annotation.RequestHeader;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;


/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.2
 * Generated source version: 2.2
 * 
 */
@WebService(name = "CodesService", targetNamespace = "https://thewsdlprovider.xyz/")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface CodesService {


    /**
     * 
     * @param requestMethodOne
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseMethodOne
     */
    @WebMethod
    @WebResult(name = "ResponseMethodOne", targetNamespace = "")
    @RequestWrapper(localName = "methodOne", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodOne")
    @ResponseWrapper(localName = "methodOneResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodOneResponse")
    public ResponseMethodOne methodOne(
        @WebParam(name = "RequestMethodOne", targetNamespace = "")
        RequestMethodOne requestMethodOne);

    /**
     * 
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseComunicacion
     */
    @WebMethod
    @WebResult(name = "ResponseTwo", targetNamespace = "")
    @RequestWrapper(localName = "methodTwo", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.VerificarComunicacion")
    @ResponseWrapper(localName = "methodTwoResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.VerificarComunicacionResponse")
    public ResponseComunicacion methodTwo();

    /**
     * 
     * @param requestMethodThreeApp
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseMethodThree
     */
    @WebMethod
    @WebResult(name = "ResponseMethodThree", targetNamespace = "")
    @RequestWrapper(localName = "methodThree", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodThree")
    @ResponseWrapper(localName = "methodThreeResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodThreeResponse")
    public ResponseMethodThree methodThree(
        @WebParam(name = "RequestMethodThreeApp", targetNamespace = "")
        RequestMethodThreeApp requestMethodThreeApp);

    /**
     * 
     * @param requestMethodFour
     * @return
     *     returns my.package.soapconsumer.models.service.getCodes.ResponseMethodFour
     */
    @WebMethod
    @WebResult(name = "ResponseMethodFour", targetNamespace = "")
    @RequestWrapper(localName = "methodFour", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodFour")
    @ResponseWrapper(localName = "methodFourResponse", targetNamespace = "https://thewsdlprovider.xyz/", className = "my.package.soapconsumer.models.service.getCodes.MethodFourResponse")
    public ResponseMethodFour methodFour(
        @WebParam(name = "RequestMethodFour", targetNamespace = "")
        RequestMethodFour requestMethodFour);

    /**
     * 
     * more methods
     *
     */
}

CodesService_Service 服务

package my.package.soapconsumer.models.service.getCodes;

import org.springframework.web.bind.annotation.RequestHeader;

import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;


/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.3.2
 * Generated source version: 2.2
 * 
 */
@WebServiceClient(name = "CodesService", targetNamespace = "https://thewsdlprovider.xyz/Codes", wsdlLocation = "https://codes.thewsdlprovider.xyz/v2/Codes?wsdl")

public class CodesService_Service
    extends Service
{

    private final static URL CODES_SERVICE_WSDL_LOCATION;
    private final static WebServiceException CODES_SERVICE_EXCEPTION;
    private final static QName CODES_SERVICE_QNAME = new QName("https://thewsdlprovider.xyz/Codes", "CodesService");

    static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL("https://codes.thewsdlprovider.xyz/v2/Codes?wsdl");

        } catch (MalformedURLException ex) {
            e = new WebServiceException(ex);
        }
        CODES_SERVICE_WSDL_LOCATION = url;
        CODES_SERVICE_EXCEPTION = e;
    }

    public CodesService_Service() {
        super(__getWsdlLocation(), CODES_SERVICE_QNAME);

    }

    public CodesService_Service(WebServiceFeature... features) {
        super(__getWsdlLocation(), CODES_SERVICE_QNAME, features);
    }

    public CodesService_Service(URL wsdlLocation) {
        super(wsdlLocation, CODES_SERVICE_QNAME);
    }

    public CodesService_Service(URL wsdlLocation, WebServiceFeature... features) {
        super(wsdlLocation, CODES_SERVICE_QNAME, features);
    }

    public CodesService_Service(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public CodesService_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
        super(wsdlLocation, serviceName, features);
    }

    /**
     * 
     * @return
     *     returns CodesService
     */
    @WebEndpoint(name = "CodesServicePort")
    public CodesService getCodesServicePort() {
        return super.getPort(new QName("https://thewsdlprovider.xyz/Codes", "CodesServicePort"), CodesService.class);
    }

    /**
     * 
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns CodesService
     */
    @WebEndpoint(name = "CodesServicePort")
    public CodesService getCodesServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("https://thewsdlprovider.xyz/Codes", "CodesServicePort"), CodesService.class, features);
    }

    private static URL __getWsdlLocation() {
        if (CODES_SERVICE_EXCEPTION!= null) {
            throw CODES_SERVICE_EXCEPTION;
        }
        return CODES_SERVICE_WSDL_LOCATION;
    }

    public String getWsdlLocation(){
        return CODES_SERVICE_WSDL_LOCATION.toString();
    }
}

我需要使用接口提供的方法或函数来测试它们我使用的是 REST 控制器:

@RestController
@RequestMapping("/codes")
public class CodigosRestController {
    @GetMapping
    public String obtainCode(){
        CodesService_Service service = new CodesService_Service();
        String code = service.getCodesServicePort().methodTwo().toString();
        return code;
    }
}

但是当我 运行 它查询 REST 端点时,我收到以下错误:

{
    "timestamp": "2022-02-18T13:44:03.234+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "trace": "com.sun.xml.internal.ws.fault.ServerSOAPFaultException: Client received SOAP Fault from server: THE SERVICE REQUIRES API KEY Please see the server log to find more detail regarding exact cause of the failure.\n\tat com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)\n\tat com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:116)\n\tat com.sun.xml.internal.ws.client.sei.StubHandler.readResponse(StubHandler.java:238)\n\tat ...
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:748)\n",
    "message": "Client received SOAP Fault from server: THE SERVICE REQUIRES API KEY Please see the server log to find more detail regarding exact cause of the failure.",
    "path": "/codes"
}

需要在 header 中发送 API KEY,但我不知道如何发送。

所以我使用 SoapUI 来测试添加这个 header 的 SOAP 端点,我收到了正确的答案:

我尝试了什么:

那么如何将 header 添加到我的界面或服务中呢?提前致谢。

要处理原始请求,您需要创建一个请求拦截器,或者只需在服务端口上的请求上下文中设置 headers。所以在你的情况下,它应该像

一样简单
@RestController
@RequestMapping("/codes")
public class CodigosRestController {
    @GetMapping
    public String obtainCode(){
        CodesService_Service service = new CodesService_Service();
        CodesService port = service.getCodesServicePort();
        // generate the headers
        Map<String, List<String>> requestHeaders = new HashMap<>();
        requestHeaders.put("apiKey",Arrays.asList("TokeApi yourtokenhere"));
        BindingProvider bindingProvider = (BindingProvider) port;   
        // set the headers on the request context
        bindingProvider.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders);

        String code = port.methodTwo().toString();
        return code;
    }

}