SpringBoot使用RestTemplate调用接口报400 Bad Request [no body]问题求解
问题原因
核心原因90%以上是 RestTemplate底层使用Apache HttpClient作为请求实现时,无请求体的GET/HEAD类请求会自动携带Content-Length: 0请求头,而Tomcat 8.5及以上版本默认会拒绝携带Content-Length/Transfer-Encoding头的GET/HEAD类请求,直接在前置校验阶段返回400错误,不会进入Spring MVC的请求映射逻辑,所以你用POST方法请求GET接口时,预期的405状态码也不会返回。
次常见原因包括:
- RestTemplate未正确注册
FormHttpMessageConverter,导致表单格式的POST请求序列化异常,请求格式不符合接口要求 - RestTemplate配置了错误的全局请求头/拦截器,或baseUrl拼接错误导致实际请求路径异常
解决步骤
首先做基础定位:使用抓包工具(Fiddler/Wireshark)或在服务端添加请求日志过滤器,对比RestTemplate发出的请求和Postman/HttpURLConnection请求的差异,重点检查GET请求是否携带了多余的Content-Length头。
再对应选择解决方案:
方案1:换回默认JDK HTTP实现(推荐,适配绝大多数场景)
RestTemplate默认使用JDK自带的SimpleClientHttpRequestFactory,不会给无请求体的GET请求附加多余的Content-Length头,直接在配置中指定即可:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory()); // 手动注册必要的消息转换器,确保表单、JSON序列化正常 restTemplate.getMessageConverters().add(new FormHttpMessageConverter()); restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); return restTemplate; } }
方案2:保留Apache HttpClient,修正请求头规则
如果必须使用Apache HttpClient作为底层实现,添加请求拦截器移除GET类请求的无效头:
import org.apache.http.HttpRequestInterceptor; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { // 构建HttpClient,添加拦截器过滤无请求体方法的无效头 HttpClient httpClient = HttpClientBuilder.create() .addInterceptorFirst((HttpRequestInterceptor) (request, context) -> { String method = request.getRequestLine().getMethod(); if (method.equals("GET") || method.equals("HEAD") || method.equals("OPTIONS") || method.equals("TRACE")) { request.removeHeaders("Content-Length"); request.removeHeaders("Transfer-Encoding"); } }) .build(); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient); RestTemplate restTemplate = new RestTemplate(factory); // 注册必要的消息转换器 restTemplate.getMessageConverters().add(new FormHttpMessageConverter()); restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); return restTemplate; } }
额外注意事项
- 发送POST表单请求时,确保请求体使用
MultiValueMap实现类,不要使用普通的HashMap - 确认请求路径、请求方法和接口定义一致,避免路径拼写错误、上下文路径缺失的问题
内容的提问来源于stack exchange,提问作者Krishna Chaitanya
相关产品推荐
相关产品推荐

