添加 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 端点,我收到了正确的答案:
我尝试了什么:
- 使用
WebServiceFeature... features
构造函数参数但是我
似乎无法将 header 添加到此 object。事实上,我
不知道这三点是什么意思
- 使用@RequestHeader 但它报告不适用于
网络方法
那么如何将 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;
}
}
我需要与 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 端点,我收到了正确的答案:
我尝试了什么:
- 使用
WebServiceFeature... features
构造函数参数但是我 似乎无法将 header 添加到此 object。事实上,我 不知道这三点是什么意思 - 使用@RequestHeader 但它报告不适用于 网络方法
那么如何将 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;
}
}