Spring Boot使用RestTemplate调用外部API无响应无报错问题求助
问题描述
- 待调用外部API地址:
https://www.example.com/en/products.json,接口返回JSON结构如下:
{ "product1": { "title": "Digital Adopter", "description": "product description", "image": "" }, "product2": { "title": "Router", "description": "product2 description", "image": "" } }
- 基于Spring Boot整合RestTemplate实现接口调用,应用启动无报错,本地服务端口配置为
8765,通过Postman访问本地接口http://localhost:8765/jkl时,既无响应返回也无错误抛出。
现有代码
启动类 JsontestApplication.java
@SpringBootApplication public class JsontestApplication { public static void main(String[] args) { SpringApplication.run(JsontestApplication.class, args); } @Bean public RestTemplate getRestTemplate() { return new RestTemplate(); } }
控制器类 Controller1.java
@RestController public class Controller1 { @Autowired RestTemplate restTemplate; @RequestMapping(value = "/jkl", method = RequestMethod.GET) public String getProductList() { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity <String> entity = new HttpEntity<String>(headers); return restTemplate.exchange("https://www.example.com/en/products.json", HttpMethod.GET, entity, String.class).getBody(); } }
问题根因
默认无参构造的RestTemplate底层使用JDK原生HttpURLConnection实现,没有配置任何超时时间,连接超时、读取超时默认值均为0(代表无限等待)。当出现网络不通、HTTPS握手异常、防火墙拦截、未配置外网代理等情况时,请求会一直阻塞,表现为接口无响应、无报错。
同时代码没有做异常捕获,即使后续超时抛出异常,也会直接返回500错误,无法直观看到错误原因。
修复方案
1. 给RestTemplate配置合理的超时时间
修改启动类中RestTemplate的Bean定义,添加超时配置,避免无限阻塞:
@Bean public RestTemplate getRestTemplate() { SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); // 连接超时:建立TCP连接的超时时间,设置为5秒 requestFactory.setConnectTimeout(5000); // 读取超时:接口响应返回的超时时间,设置为10秒 requestFactory.setReadTimeout(10000); return new RestTemplate(requestFactory); }
2. 控制器添加异常捕获,打印错误日志
修改控制器方法,捕获调用异常,避免错误静默:
@RestController public class Controller1 { @Autowired RestTemplate restTemplate; @RequestMapping(value = "/jkl", method = RequestMethod.GET) public String getProductList() { try { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); HttpEntity<String> entity = new HttpEntity<>(headers); ResponseEntity<String> resp = restTemplate.exchange( "https://www.example.com/en/products.json", HttpMethod.GET, entity, String.class ); return resp.getBody(); } catch (RestClientException e) { // 控制台打印完整异常栈,方便定位问题 e.printStackTrace(); return "调用外部接口失败:" + e.getMessage(); } } }
3. 针对性排查特殊场景
配置超时后再次调用接口,会直接抛出明确的异常信息,可根据异常对应处理:
- 若抛出
Connection timed out:先在应用所在机器直接用curl等工具测试目标接口连通性,确认是否存在网络拦截、是否需要配置外网代理 - 若抛出
SSLHandshakeException:说明目标站点HTTPS证书不受JDK信任,测试环境可临时配置跳过SSL校验,生产环境请将目标站点证书导入JDK信任库 - 若抛出
UnknownHostException:说明DNS解析失败,检查服务器DNS配置
内容的提问来源于stack exchange,提问作者RuwanH
相关产品推荐
相关产品推荐

