答案 0 :(得分:30)
正如igor.zh所指出的,如果使用Spring的HttpComponentsMessageSender类,就会出现这个问题。更确切地说,如果您将自己的HttpClient实例传递给HttpComponentsMessageSender构造函数,这只是一个问题 - 否则会自动处理该问题。
从spring-ws 2.1.4开始,默认构造函数中使用的HttpComponentsMessageSender.RemoveSoapHeadersInterceptor子类被公开以解决此问题(请参阅https://jira.spring.io/browse/SWS-835),因此可以在您自己的HttpClient实例中使用写自己的课来做。它还会清除HTTP.TRANSFER_ENCODING标头。
使用HttpClientBuilder.addInterceptorFirst方法将此拦截器注入您自己的HttpClient实例。下面的例子使用XML bean连线。如果有人知道构建HttpClient实例的更简洁的方法(除了编写工厂bean类),我全都是耳朵!
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create"/>
<bean id="interceptedHttpClientBuilder" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="httpClientBuilder" />
<property name="targetMethod" value="addInterceptorFirst"> </property>
<property name="arguments">
<list>
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender.RemoveSoapHeadersInterceptor"/>
</list>
</property>
</bean>
<bean id="httpClient" factory-bean="interceptedHttpClientBuilder" factory-method="build" />
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory"/>
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="httpClient" ref="httpClient"/>
</bean>
</property>
</bean>
或者,如果可以的话,只需允许HttpComponentsMessageSender构建自己的HttpClient实例,而不是将其传递给它。关于这一点的注意事项:从spring-ws 2.2.0-RELEASE开始,HttpComponentsMessageSender的默认构造函数继续使用DefaultHttpClient类,现在不推荐使用它。希望这将在未来的版本中得到解决。
答案 1 :(得分:29)
答案 2 :(得分:13)
当我使用http://docs.spring.io/spring-ws/site/apidocs/org/springframework/ws/transport/http/HttpComponentsMessageSender.html作为Spring WebService Message Sender时,这种情况发生在我身上。在这种情况下,像HttpPut或HttpRequest这样的东西不容易访问,因此,使用HttpClientBuilder构建HttpClient,我最终在罪魁祸首RequestContent之前插入一个HttpRequestInterceptor:
private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{
@Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present");
}
}
...
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.addInterceptorFirst(new CcontentLengthHeaderRemover());
答案 3 :(得分:3)
John Rix's answer有正确的想法。以下是使用普通java的方法:
HttpClient client = HttpClients.custom()
.addInterceptorFirst(new RemoveSoapHeadersInterceptor())
.build();
答案 4 :(得分:1)
如果您结帐http://docjar.org/docs/api/org/apache/http/protocol/RequestContent.html,您会注意到如果您自己设置了它会抛出该异常。因此,内部工作自动设置内容长度。这也意味着,要将其设置为“0”,您需要将实体设置为null。
答案 5 :(得分:0)
@John Rix的答案 这段代码帮助解决了问题
private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{
@Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
request.removeHeaders(HTTP.CONTENT_LEN);// fighting org.apache.http.protocol.RequestContent's ProtocolException("Content-Length header already present");
}
}
HttpClient client = HttpClients.custom()
.addInterceptorFirst(new ContentLengthHeaderRemover())
.build();