Динамическое создание настраиваемого HTTP-заголовка с помощью клиента Spring-WS

Как вы устанавливаете пользовательский заголовок HTTP (а не заголовок SOAP) динамически на стороне клиента при использовании Spring-WS?

java,spring,http,header,spring-ws,

28

Ответов: 7


22 ование принято
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;
}

}

конфигурации:

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

22

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

9

При использовании интеграции пружин 3 и интеграции пружин-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" />

1

Метод webServiceTemplate.marshalSendAndReceive (запроса) Spring использует метод HttpComponentsMessageSender для отправки SOAP-сообщения по сети, и это дополнительно использует WebServiceConnection для http-соединения с сервером. Все, что вам нужно сделать, это написать свой собственный HttpComponentsMessageSender и установить cookie в postMethod.

Код отправителя Custome:

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

Конфигурация пружины:

<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. Таким образом, каждый запрос будет иметь свой настраиваемый файл cookie перед вызовом HTTP.


1

Фактически, это обновленная версия ответа @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
            }
        });
    }

}
Java, весна, HTTP, заголовок, весна-WS,
Похожие вопросы