如何在使用Spring-WS時在客戶端動態地設置自定義HTTP頭(不是SOAP頭)?使用Spring-WS客戶端動態設置自定義HTTP頭
回答
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>
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);
}
}
該解決方案比使用客戶端攔截器更靈活。恕我直言,它應該是首選。 – 2013-09-14 10:27:00
我得到以下異常 java.lang.ClassCastException: 在這條線context.getConnection() org.springframework.ws.transport.http.HttpServletConnection不能轉換爲org.springframework.ws.transport.http .CommonsHttpConnection – 2014-05-03 07:19:38
僅供參考,'org.springframework.ws.transport.http.CommonsHttpConnection'已被棄用,以支持'org.springframework.ws.transport.http.HttpComponentsConnection'。 – ZeroOne 2015-05-20 14:18:03
以下片段已用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);
的問題是「你如何設置自定義HTTP頭(不是SOAP頭)「,但是這個答案實際上增加了一個SOAP頭,而不是一個HTTP頭。 – ZeroOne 2015-05-20 13:44:13
Spring的webServiceTemplate.marshalSendAndReceive(request)方法內部使用HttpComponentsMessageSender到通過網絡發送SOAP消息,這還使用WebServiceConnection使與服務器的HTTP連接。你所要做的就是編寫你自己定製的HttpComponentsMessageSender並在postMethod中設置cookie。
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;
}
}
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>
此我簡單地得到豆webServiceTemplate並調用marshalSendAndReceive方法後。因此,在進行HTTP調用之前,每個請求都會設置自定義cookie。
當使用彈簧一體化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" />
實際上,它是@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
}
});
}
}
- 1. Akka Http客戶端:自定義標頭
- 2. 自定義Http客戶端的動態URL - Spring-XD
- 3. 帶自定義HTTP客戶端的WebView
- 4. 如何設置自定義用戶代理與Apache HTTP客戶端庫4.1?
- 5. 設置HTTP頭處理器:HTTP客戶端
- 6. SoapClient設置自定義HTTP標頭
- 7. SDWebImage並設置自定義HTTP標頭?
- 8. IIS設置接收自定義HTTP頭
- 9. 使用JavaScript修改HTTP頭客戶端
- 10. 使用Apache HTTP客戶端自定義重試處理程序?
- 11. HTTP頭自動設置
- 12. WebApiCodeGen客戶端自定義
- 13. 在wcf客戶端動態設置端點地址(使用net tcp綁定)
- 14. 如何在RESTEasy客戶端框架中設置HTTP標頭?
- 15. 使用HttpURLConnection設置自定義標頭
- 16. 如何在CXF客戶端動態添加HTTP頭文件?
- 17. 爲HTTP客戶端設置代理
- 18. Nginx的proxy_pass塊客戶端頭和強制nginx使用自定義標頭
- 19. Akka HTTP客戶端websocket流的定義
- 20. 如何將自定義Content-Type設置爲jax-rs客戶端?
- 21. 如何從繼承自SoapHttpClientProtocol的客戶端類設置HTTP標頭
- 22. 如何將自定義UI添加到動態CRM客戶端
- 23. 使用Http客戶端
- 24. Google App Engine - Web客戶端的自定義URL,移動客戶端的端點?
- 25. 使用Commons HTTPClient自定義HTTP標頭?
- 26. Angular:使用自定義HTTP頭條目
- 27. 使用JPlayer的自定義HTTP頭
- 28. 使用XmlRpcClient自定義HTTP標頭
- 29. 如何使用pdf.js設置客戶端的範圍頭?
- 30. 客戶端通常發送http頭
對於將來的用戶來說,好的答案是使用HttpComponentsConnection而不是CommonsHttpConnection,因爲它已被棄用。 – dardo 2012-07-02 20:13:38
運行JUnit測試時工作嗎?在我的情況下,它並不是因爲'context.getConnection()'返回'MockSenderConnection'。我正在使用'MockWebServiceServer'進行單元測試。 – Gooseman 2015-12-31 00:21:00