2010-07-02 17 views

Respuesta

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

} 

config:

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

Buena respuesta, para los usuarios en el futuro, utilice HttpComponentsConnection en lugar de CommonsHttpConnection, ya que ha quedado en desuso. – dardo

+0

¿Funciona al ejecutar pruebas JUnit? En mi caso, no fue así porque 'context.getConnection()' devuelve 'MockSenderConnection'. Estoy usando 'MockWebServiceServer' para pruebas unitarias. – Gooseman

20

ClientInterceptor funciona muy bien para el valor de encabezado estático. Pero no es posible usarlo cuando se debe aplicar un valor diferente por cada solicitud. En ese caso WebServiceMessageCallback es útil:

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

Esta solución es más flexible que usar el interceptor del cliente. En mi humilde opinión, debería ser el preferido. –

+0

Me estoy poniendo siguiente excepción java.lang.ClassCastException: en esta línea context.getConnection() org.springframework.ws.transport.http.HttpServletConnection no se puede convertir a org.springframework.ws.transport.http .CommonsHttpConnection –

+3

FYI, 'org.springframework.ws.transport.http.CommonsHttpConnection' ha quedado en desuso en favor de' org.springframework.ws.transport.http.HttpComponentsConnection'. – ZeroOne

0

El siguiente fragmento ha sido probado con Spring 4.0. Se añade un WebServiceMessageCallback a un método 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); 
+0

La pregunta era "¿Cómo se establece una costumbre HTTP encabezado (no encabezado SOAP) ", pero esta respuesta en realidad agrega un encabezado SOAP, no un encabezado HTTP. – ZeroOne

1

webServiceTemplate.marshalSendAndReceive de primavera (petición) utiliza internamente HttpComponentsMessageSender para enviar el mensaje SOAP a través de la red y esto aún más WebServiceConnection utiliza para hacer la conexión con el servidor HTTP. Todo lo que tiene que hacer es escribir su propio HttpComponentsMessageSender personalizado y establecer la cookie dentro de PostMethod.

Custome del código de remitente: Configuración

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

primavera:

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

Después de esto simplemente obtener webServiceTemplate frijol y llamar al método marshalSendAndReceive. Por lo tanto, cada solicitud tendrá su cookie personalizada antes de realizar una llamada HTTP.

9

Cuando se utiliza de integración de resorte 3 y del resorte de integración-ws, el código siguiente se puede utilizar para el manejo de la solicitud:

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

    return true; 
} 

El interceptor se puede conectar a la pasarela de salida de la siguiente manera:

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

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

En realidad, es una versión actualizada de la respuesta @Tomasz, pero proporciona una nueva API Spring-WS, accesos directos Java 8, y se preocupa por crear una instancia WebServiceMessageCallback con un método diferente.

Creo que es más obvio y autosuficiente.

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

} 
+0

¿Cómo usaría esta clase? Ya tengo una clase de servicio generada a partir de WSDL. – Pretty

+0

@Pretty, usa una URL y una carga especificada allí, y pásalas aquí – Andrew

Cuestiones relacionadas