Spring Boot3迁移:TestRestTemplate调用HttpClient5报Target host空指针
问题背景
从Spring Boot 2.x迁移到3.x后,原本正常的集成测试抛出NullPointerException: Target host错误。测试代码通过@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)启动随机端口服务,使用TestRestTemplate调用相对路径接口,调试确认TestRestTemplate已持有正确的主机URI(如http://localhost:64877),但执行时HttpClient5仍提示主机为null。项目依赖Apache HttpClient5,指定或不指定版本均无改善。
最终定位问题出在自定义的RestTemplateCustomizer中,使用HttpClients.createMinimal()初始化HttpClient:
@Bean public RestTemplateCustomizer customRestTemplateCustomizer() { return new RestTemplateCustomizer() { @Override public void customize(RestTemplate restTemplate) { restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClients.createMinimal())); restTemplate.setErrorHandler(new ApiResponseErrorHandler()); } }; }
移除setRequestFactory代码或改用HttpClients.createDefault()后,测试恢复正常。
原因分析
HttpClients.createMinimal()创建的是极简版HttpClient实例,仅保留最基础的HTTP执行能力,缺少两个关键组件:
- 路由规划器(
DefaultRoutePlanner):负责将相对路径与TestRestTemplate持有的基础URI拼接为完整请求地址 - URI解析预处理逻辑:处理主机补全、路径合并等核心操作
而TestRestTemplate调用相对路径接口时,完全依赖HttpClient的路由机制自动补全完整URI。极简版HttpClient缺少这些组件,导致无法正确解析目标主机,最终抛出NullPointerException。
相比之下,HttpClients.createDefault()会初始化完整的客户端组件,包括路由规划器、连接池等,能够正常处理相对路径到完整URI的转换。
解决方案
方案1:改用createDefault()初始化HttpClient
保留自定义配置的同时,替换为具备完整能力的默认客户端:
@Bean public RestTemplateCustomizer customRestTemplateCustomizer() { return restTemplate -> { restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(HttpClients.createDefault())); restTemplate.setErrorHandler(new ApiResponseErrorHandler()); }; }
方案2:为极简版HttpClient手动添加路由规划器
如果确实需要使用极简客户端,手动配置DefaultRoutePlanner来支持URI解析:
@Bean public RestTemplateCustomizer customRestTemplateCustomizer() { return restTemplate -> { HttpClient httpClient = HttpClients.custom() .setRoutePlanner(new DefaultRoutePlanner(DefaultSchemePortResolver.INSTANCE)) .build(); restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); restTemplate.setErrorHandler(new ApiResponseErrorHandler()); }; }
方案3:移除自定义RequestFactory配置
如果不需要自定义HttpClient,直接删除setRequestFactory代码,使用Spring Boot自动配置的默认RequestFactory即可:
@Bean public RestTemplateCustomizer customRestTemplateCustomizer() { return restTemplate -> { restTemplate.setErrorHandler(new ApiResponseErrorHandler()); }; }
内容的提问来源于stack exchange,提问作者Sunil

