Spring Integration4:Http Outbound Gateway的RestTemplate覆盖Accept头问题求助
从你的日志细节里能发现矛盾点:
DefaultHttpHeaderMapper已经正确把Accept头设置为application/vnd.dsths.services-v8+xml- 但紧接着
RestTemplate又将Accept头重置成了默认的[text/plain, application/json, application/*+json, */*]
这是Spring Integration 4中HttpOutboundGateway的一个特性:当你指定expected-response-type="java.lang.String"时,RestTemplate会根据这个响应类型自动匹配对应的HttpMessageConverter(这里是StringHttpMessageConverter),然后用该转换器默认支持的媒体类型覆盖之前通过HeaderMapper设置的Accept头。而StringHttpMessageConverter默认支持的媒体类型正好是日志里显示的那几个,所以你的自定义Accept头被覆盖,导致服务端因接收不符合要求的请求头返回400错误。
这里提供两种可行的解决思路:
方式一:自定义RestTemplate,修改消息转换器的支持类型
创建一个自定义的RestTemplate,调整StringHttpMessageConverter仅支持你需要的媒体类型,这样RestTemplate就不会自动生成默认的Accept头了。
配置示例:
<!-- 自定义RestTemplate,指定String转换器支持的媒体类型 --> <bean id="customRestTemplate" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/vnd.dsths.services-v8+xml</value> </list> </property> </bean> <!-- 如果需要处理其他类型的响应,比如JSON,记得添加对应的转换器 --> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/> </list> </property> </bean> <!-- 出站网关引用自定义RestTemplate --> <int-http:outbound-gateway url-expression="headers.restResourceUrl" http-method-expression="headers.httpMethod" expected-response-type="java.lang.String" rest-template="customRestTemplate"> </int-http:outbound-gateway>
方式二:移除expected-response-type,通过下游处理器转换响应
如果场景允许,可以不指定expected-response-type,让响应以ResponseEntity形式返回,这样RestTemplate不会自动覆盖Accept头。之后在下游消息处理器中将响应体转换成String类型。
调整后的配置示例:
<int-http:outbound-gateway url-expression="headers.restResourceUrl" http-method-expression="headers.httpMethod" expected-response-type="org.springframework.http.ResponseEntity" reply-channel="responseProcessingChannel"> </int-http:outbound-gateway> <!-- 下游处理器:将ResponseEntity的body转换为String --> <int:service-activator input-channel="responseProcessingChannel" ref="responseHandler" method="processResponse"/> <bean id="responseHandler" class="your.package.ResponseHandler"/>
对应的处理器类示例:
public class ResponseHandler { public String processResponse(ResponseEntity<byte[]> response) { if (response.getStatusCode().is2xxSuccessful()) { return new String(response.getBody(), StandardCharsets.UTF_8); } // 处理错误场景 throw new RuntimeException("请求失败,状态码:" + response.getStatusCode()); } }
验证要点
修改完成后,重新查看日志,确认RestTemplate不再重置Accept头,而是保留你自定义的application/vnd.dsths.services-v8+xml,此时应该就能解决400错误了。
内容的提问来源于stack exchange,提问作者Ashok.N

