2010-07-02 15 views

Odpowiedz

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

Dobra odpowiedź, dla użytkowników w przyszłości, użyj HttpComponentsConnection zamiast CommonsHttpConnection, ponieważ jest przestarzała. – dardo

+0

Czy działa podczas uruchamiania testów JUnit? W moim przypadku nie, ponieważ 'context.getConnection()' zwraca 'MockSenderConnection'. Używam "MockWebServiceServer" do testowania jednostek. – Gooseman

20

ClientInterceptor działa świetnie dla statycznej wartości nagłówka. Nie można jednak jej użyć, jeśli do każdego żądania należy zastosować inną wartość. W takim przypadku WebServiceMessageCallback jest pomocne:

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

To rozwiązanie jest bardziej elastyczne niż użycie przechwytywacza klienta. IMHO, powinien być preferowany. –

+0

Dostaję następujący wyjątek java.lang.ClassCastException: na tej linii context.getConnection() org.springframework.ws.transport.http.HttpServletConnection nie mogą być oddane do org.springframework.ws.transport.http .CommonsHttpConnection –

+3

FYI, 'org.springframework.ws.transport.http.CommonsHttpConnection' został wycofany na rzecz' org.springframework.ws.transport.http.HttpComponentsConnection'. – ZeroOne

0

Poniższy fragment został przetestowany z wiosny 4.0. Załącza on WebServiceMessageCallback do sprężyny za webServiceTemplate.marshalSendAndReceive metodę 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

Pytanie brzmiało „Jak można ustawić niestandardowy HTTP nagłówek (nie nagłówek SOAP) ", ale ta odpowiedź faktycznie dodaje nagłówek SOAP, a nie nagłówek HTTP. – ZeroOne

1

(żądania) wewnętrznie używa HttpComponentsMessageSender aby wysłać wiadomość SOAP za pośrednictwem sieci, a to dodatkowo wykorzystuje WebServiceConnection dokonać połączenia HTTP z serwerem. Wszystko, co musisz zrobić, to napisać własny HttpComponentsMessageSender i ustawić plik cookie wewnątrz postMethod.

custome kod nadawca:

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

Wiosna Konfiguracja:

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

Po tym ja po prostu dostać fasoli webServiceTemplate i wywołać metodę marshalSendAndReceive. Więc każde żądanie będzie miało ustawiony niestandardowy plik cookie przed wywołaniem HTTP.

9

Przy użyciu integracji sprężyny 3 i sprężyste integracją WS następujący kod może być wykorzystywane do obsługi żądania:

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

    return true; 
} 

Interceptor może być połączony z bramką wychodzącego w następujący sposób:

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

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

W rzeczywistości jest to zaktualizowana wersja odpowiedzi @Tomasz, ale zapewnia nowy interfejs API Spring-WS, skróty Java 8 i dba o tworzenie instancji WebServiceMessageCallback za pomocą osobnej metody.

Uważam, że jest bardziej oczywiste i samowystarczalne.

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

Jak korzystać z tej klasy? Mam już klasę usług wygenerowaną z WSDL. – Pretty

+0

@Pretty, użyj podanego adresu URL i ładunku i przekaż je tutaj – Andrew

Powiązane problemy