使用Spring-WS客户端动态设置自定义HTTP标头

在使用Spring-WS时,如何在客户端动态设置自定义HTTP头(而不是SOAP头)?

public class AddHttpHeaderInterceptor implements ClientInterceptor { public boolean handleFault(MessageContext messageContext) throws WebServiceClientException { return true; } public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException { TransportContext context = TransportContextHolder.getTransportContext(); CommonsHttpConnection connection = (CommonsHttpConnection) context.getConnection(); PostMethod postMethod = connection.getPostMethod(); postMethod.addRequestHeader( "fsreqid", "123456" ); return true; } public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException { return true; } } 

配置:

   ...       

ClientInterceptor非常适合静态标头值。 但是,当每个请求应该应用不同的值时,不可能使用它。 在这种情况下, WebServiceMessageCallback很有帮助:

 final String dynamicParameter = //... webServiceOperations.marshalSendAndReceive(request, new WebServiceMessageCallback() { void doWithMessage(WebServiceMessage message) { TransportContext context = TransportContextHolder.getTransportContext(); CommonsHttpConnection connection = (CommonsHttpConnection) context.getConnection(); PostMethod postMethod = connection.getPostMethod(); postMethod.addRequestHeader( "fsreqid", dynamicParameter ); } } 

使用spring integration 3和spring integration-ws时,可以使用以下代码处理请求:

 public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException { TransportContext context = TransportContextHolder.getTransportContext(); HttpUrlConnection connection = (HttpUrlConnection) context .getConnection(); connection.getConnection().addRequestProperty("HEADERNAME", "HEADERVALUE"); return true; } 

Interceptor可以通过以下方式连接到出站网关:

    

Spring的webServiceTemplate.marshalSendAndReceive(request)方法在内部使用HttpComponentsMessageSender通过网络发送SOAP消息,这进一步使用WebServiceConnection与服务器建立http连接。 您所要做的就是编写自己的自定义HttpComponentsMessageSender并在postMethod中设置cookie。

客户发件人代码:

  package com.swap.ws.sender; import java.io.IOException; import java.net.URI; import javax.annotation.Resource; import org.apache.http.client.methods.HttpPost; import org.apache.log4j.Logger; import org.springframework.stereotype.Service; import org.springframework.ws.transport.WebServiceConnect ion; import org.springframework.ws.transport.http.HttpComponen tsConnection; /** * * @author swapnil Z */ @Service("urlMessageSender") public class CustomHttpComponentsMessageSender extends org.springframework.ws.transport.http.HttpComponen tsMessageSender { private static Logger _logger = Logger.getLogger(""); @Override public WebServiceConnection createConnection(URI uri) throws IOException { String cookie = null; HttpComponentsConnection conn = (HttpComponentsConnection) super .createConnection(uri); HttpPost postMethod = conn.getHttpPost(); cookie = ""; postMethod.addHeader("Cookie", cookie); return conn; } } 

弹簧配置:

           />  

在此之后,我只需获取bean webServiceTemplate并调用marshalSendAndReceive方法。 因此,每个请求都会在进行HTTP调用之前设置自定义cookie。

实际上,它是@Tomasz的答案的更新版本,但提供了一个新的Spring-WS API,Java 8快捷方式,并且关注使用单独的方法创建WebServiceMessageCallback实例。

我相信它更加明显和自给自足。

 final class Service extends WebServiceGatewaySupport { /** * @param URL the URI to send the message to * @param payload the object to marshal into the request message payload * @param headers HTTP headers to add to the request */ public Object performRequestWithHeaders(String URL, Object payload, Map headers) { return getWebServiceTemplate() .marshalSendAndReceive(URL, payload, getRequestCallback(headers)); } /** * Returns a {@code WebServiceMessageCallback} instance with custom HTTP headers. */ private WebServiceMessageCallback getRequestCallback(Map headers) { return message -> { TransportContext context = TransportContextHolder.getTransportContext(); HttpUrlConnection connection = (HttpUrlConnection)context.getConnection(); addHeadersToConnection(connection, headers); }; } /** * Adds all headers from the {@code headers} to the {@code connection}. */ private void addHeadersToConnection(HttpUrlConnection connection, Map headers){ headers.forEach((name, value) -> { try { connection.addRequestHeader(name, value); } catch (IOException e) { e.printStackTrace(); // or whatever you want } }); } } 

使用java 1.8的示例方法:如何添加HTTP标头:

 public void executeObjectWebservice(String id) { ExecuteObject request = new ExecuteObject(); getWebServiceTemplate().marshalSendAndReceive("http://url/webservice-test/uc4ws", new ObjectFactory().createExecuteObject(request), new WebServiceMessageCallback() { public void doWithMessage(WebServiceMessage message) throws IOException { TransportContext context = TransportContextHolder.getTransportContext(); HttpUrlConnection connection = (HttpUrlConnection) context.getConnection(); connection.addRequestHeader("ID", id); } }); } 

说明 :使用getWebServiceTemplate()。marshalSendAndReceive,如下所示: https ://spring.io/guides/gs/consuming-web-service/

第一个参数是URI,第二个是与请求一起发送的对象。 作为第三个参数,您可以添加为function

 new WebServiceMessageCallback() 

你重写public void doWithMessage发送请求之前调用此方法。 您可以在其中访问该消息并添加请求标题

 TransportContext context = TransportContextHolder.getTransportContext(); HttpUrlConnection connection = (HttpUrlConnection) context.getConnection(); connection.addRequestHeader("ID", id); 

以下片段已在Spring 4.0中测试过。 它将一个WebServiceMessageCallback附加到org.springframework.ws.client.core.WebServiceTemplate

 final String DYNAMICVALUE = "myDynamo"; WebServiceMessageCallback wsCallback = new WebServiceMessageCallback() { public void doWithMessage(WebServiceMessage message) { try { SoapMessage soapMessage = (SoapMessage)message; SoapHeader header = soapMessage.getSoapHeader(); header.addAttribute(new QName("myHeaderElement"), DYNAMICVALUE); } catch (Exception e) { e.printStackTrace(); } } }; JAXBElement response = (JAXBElement) wsTemplate.marshalSendAndReceive(MyWsOP, wsCallback);