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

时间:2022-07-03 11:42:48

How do you set a custom HTTP header (not SOAP header) dynamically on the client side when using Spring-WS?

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

7 个解决方案

#1


23  

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;
}

}

config:

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    ...
    <property name="interceptors">
        <list>
            <bean class="com.blah.AddHttpHeaderInterceptor" />
        </list>
    </property>
</bean>

#2


22  

ClientInterceptor works great for static header value. But it is not possible to use it when a different value should be applied per each request. In that case WebServiceMessageCallback is helpful:

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 );
        }
}

#3


10  

When using spring integration 3 and spring integration-ws, the following code can be used for handling the request:

使用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;
}

The Interceptor can be connected to the outbound gateway in the following way:

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

<ws:outbound-gateway ...            
        interceptor="addPasswordHeaderInterceptor" >
</ws:outbound-gateway>

<bean id="addPasswordHeaderInterceptor class="com.yourfirm.YourHttpInterceptor" />

#4


1  

Spring's webServiceTemplate.marshalSendAndReceive(request) method internally uses HttpComponentsMessageSender to send the SOAP message over the network and this further uses WebServiceConnection to make http connection with the server. All you have to do is to write your own custom HttpComponentsMessageSender and set the cookie inside postMethod.

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

Custome sender code:

客户发件人代码:

    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 = "<Your Custom Cookie>";

postMethod.addHeader("Cookie", cookie);

return conn;
}
}

Spring Configuration :

弹簧配置:

<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMe ssageFactory" />

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshalle r">
<property name="contextPath" value="com.swap.provision" />
</bean>

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServi ceTemplate">
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="marshaller"></property>
<property name="unmarshaller" ref="marshaller"></property>
<property name="messageSender" ref="urlMessageSender"/>
<property name="defaultUri" value=<Server URL> />
</bean>

After this I simply get bean webServiceTemplate and call marshalSendAndReceive method. So every request will have its custom cookie set before making HTTP call.

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

#5


1  

Actually, it is an updated version of the @Tomasz's answer, but provides a new Spring-WS API, Java 8 shortcuts, and cares about creating a WebServiceMessageCallback instance with a separate method.

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

I believe it is more obvious and self-sufficient.

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

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<String, String> headers) {
        return getWebServiceTemplate()
                .marshalSendAndReceive(URL, payload, getRequestCallback(headers));
    }

    /**
     * Returns a {@code WebServiceMessageCallback} instance with custom HTTP headers.
     */
    private WebServiceMessageCallback getRequestCallback(Map<String, String> 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<String, String> headers){
        headers.forEach((name, value) -> {
            try {
                connection.addRequestHeader(name, value);
            } catch (IOException e) {
                e.printStackTrace(); // or whatever you want
            }
        });
    }

}

#6


1  

Example Method with java 1.8: How to add a HTTP header:

使用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);
                    }
                });    
        }

Explanation: Use the getWebServiceTemplate().marshalSendAndReceive as described for example here: https://spring.io/guides/gs/consuming-web-service/

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

First parameter is the URI, second is the object which shall be send with the request. As third Parameter you can add as function

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

new WebServiceMessageCallback()

where you override the public void doWithMessage. This method gets called before the request is sent. Within you can access the message and add a request Header through

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

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

#7


-1  

The following fragment has been tested with Spring 4.0. It appends a WebServiceMessageCallback to a org.springframework.ws.client.core.WebServiceTemplate

以下片段已在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<MyWsResponse> response = (JAXBElement<MyWsResponse>)
        wsTemplate.marshalSendAndReceive(MyWsOP, wsCallback);

#1


23  

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;
}

}

config:

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    ...
    <property name="interceptors">
        <list>
            <bean class="com.blah.AddHttpHeaderInterceptor" />
        </list>
    </property>
</bean>

#2


22  

ClientInterceptor works great for static header value. But it is not possible to use it when a different value should be applied per each request. In that case WebServiceMessageCallback is helpful:

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 );
        }
}

#3


10  

When using spring integration 3 and spring integration-ws, the following code can be used for handling the request:

使用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;
}

The Interceptor can be connected to the outbound gateway in the following way:

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

<ws:outbound-gateway ...            
        interceptor="addPasswordHeaderInterceptor" >
</ws:outbound-gateway>

<bean id="addPasswordHeaderInterceptor class="com.yourfirm.YourHttpInterceptor" />

#4


1  

Spring's webServiceTemplate.marshalSendAndReceive(request) method internally uses HttpComponentsMessageSender to send the SOAP message over the network and this further uses WebServiceConnection to make http connection with the server. All you have to do is to write your own custom HttpComponentsMessageSender and set the cookie inside postMethod.

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

Custome sender code:

客户发件人代码:

    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 = "<Your Custom Cookie>";

postMethod.addHeader("Cookie", cookie);

return conn;
}
}

Spring Configuration :

弹簧配置:

<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMe ssageFactory" />

<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshalle r">
<property name="contextPath" value="com.swap.provision" />
</bean>

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServi ceTemplate">
<constructor-arg ref="messageFactory" />
<property name="marshaller" ref="marshaller"></property>
<property name="unmarshaller" ref="marshaller"></property>
<property name="messageSender" ref="urlMessageSender"/>
<property name="defaultUri" value=<Server URL> />
</bean>

After this I simply get bean webServiceTemplate and call marshalSendAndReceive method. So every request will have its custom cookie set before making HTTP call.

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

#5


1  

Actually, it is an updated version of the @Tomasz's answer, but provides a new Spring-WS API, Java 8 shortcuts, and cares about creating a WebServiceMessageCallback instance with a separate method.

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

I believe it is more obvious and self-sufficient.

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

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<String, String> headers) {
        return getWebServiceTemplate()
                .marshalSendAndReceive(URL, payload, getRequestCallback(headers));
    }

    /**
     * Returns a {@code WebServiceMessageCallback} instance with custom HTTP headers.
     */
    private WebServiceMessageCallback getRequestCallback(Map<String, String> 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<String, String> headers){
        headers.forEach((name, value) -> {
            try {
                connection.addRequestHeader(name, value);
            } catch (IOException e) {
                e.printStackTrace(); // or whatever you want
            }
        });
    }

}

#6


1  

Example Method with java 1.8: How to add a HTTP header:

使用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);
                    }
                });    
        }

Explanation: Use the getWebServiceTemplate().marshalSendAndReceive as described for example here: https://spring.io/guides/gs/consuming-web-service/

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

First parameter is the URI, second is the object which shall be send with the request. As third Parameter you can add as function

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

new WebServiceMessageCallback()

where you override the public void doWithMessage. This method gets called before the request is sent. Within you can access the message and add a request Header through

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

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

#7


-1  

The following fragment has been tested with Spring 4.0. It appends a WebServiceMessageCallback to a org.springframework.ws.client.core.WebServiceTemplate

以下片段已在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<MyWsResponse> response = (JAXBElement<MyWsResponse>)
        wsTemplate.marshalSendAndReceive(MyWsOP, wsCallback);