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

发布于 2024-09-08 01:15:34 字数 56 浏览 2 评论 0原文

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

柏拉图鍀咏恒 2024-09-15 01:15:34
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();
     HttpComponentsConnection connection =(HttpComponentsConnection) context.getConnection();
     connection.addRequestHeader("name", "suman");

    return true;
}

public boolean handleResponse(MessageContext messageContext)
        throws WebServiceClientException {
    return true;
}

}

配置:

    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    ...
    <property name="interceptors">
        <list>
            <bean class="com.blah.AddHttpHeaderInterceptor" />
        </list>
    </property>
</bean>
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();
     HttpComponentsConnection connection =(HttpComponentsConnection) context.getConnection();
     connection.addRequestHeader("name", "suman");

    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>
没有你我更好 2024-09-15 01:15:34

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

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:

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 );
        }
}
我一直都在从未离去 2024-09-15 01:15:34

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

拦截器可以通过以下方式连接到出站网关:

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

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

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

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:

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

<bean id="addPasswordHeaderInterceptor class="com.yourfirm.YourHttpInterceptor" />
谜泪 2024-09-15 01:15:34

实际上,它是 @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<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
            }
        });
    }

}

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.

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

}
蓝天白云 2024-09-15 01:15:34

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,第二个参数是随请求一起发送的对象。作为第三个参数,您可以添加为

new WebServiceMessageCallback()

覆盖 public void doWithMessage 的函数。在发送请求之前调用此方法。您可以在其中访问消息并通过以下方式添加请求标头

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

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

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/

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

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

TransportContext context = TransportContextHolder.getTransportContext();
HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
connection.addRequestHeader("ID", id);
就此别过 2024-09-15 01:15:34

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

postMethod.addHeader("Cookie", cookie);

return conn;
}
}

Spring 配置:

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

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

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.

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.

恰似旧人归 2024-09-15 01:15:34

以下片段已使用 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);

The following fragment has been tested with Spring 4.0. It appends a WebServiceMessageCallback to a 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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文