使用RestTemplate获取值时无法展示JSON且页面报错如何解决?
问题描述
预期实现页面名称与对应HTTP状态码的展示功能,但调用myServicePinger方法时程序直接崩溃,报错效果如下:
对应实现代码如下:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; @Service public class EndpointsService { @Lazy @Autowired private RestTemplate restTemplate; @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public int myServicePinger() { HttpStatus statusCode = restTemplate.getForEntity("http://www.google.com/", String.class).getStatusCode(); return statusCode.value(); //log.info(statusCode); } public List<Endpoints> getEndpoints() { myServicePinger(); int code = myServicePinger(); return List.of( new Endpoints( "google.com", code ) ); } }
问题根因
崩溃由两个核心问题导致:
RestTemplate的Bean定义错误:你把@Bean修饰的restTemplate()方法写在了@Service标注的业务类中,Spring不会正确初始化这个Bean,加上你加了@Lazy注解,注入的restTemplate对象实际为null,调用方法时直接触发空指针。- 缺少异常处理:
RestTemplate默认行为是只要HTTP响应状态不是2xx系列,或者出现网络连接失败、超时等问题,就会直接抛出异常,你没有做任何捕获处理,异常直接抛到上层就会导致页面崩溃。
另外代码里还有一处冗余问题:getEndpoints()方法里连续调用了两次myServicePinger(),第一次的返回值没有被使用,平白多了一次外网请求开销。
修复步骤
- 单独定义RestTemplate配置类
把RestTemplate的Bean定义从Service类中移出去,新建独立的配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class WebConfig { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
- 修正业务类代码
移除Service类里多余的RestTemplateBean定义和@Lazy注解,给HTTP请求加异常捕获,删掉重复的方法调用:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClientResponseException; import org.springframework.web.client.RestTemplate; import java.util.List; @Service public class EndpointsService { @Autowired private RestTemplate restTemplate; private int myServicePinger(String targetUrl) { try { return restTemplate.getForEntity(targetUrl, String.class) .getStatusCode() .value(); } catch (RestClientResponseException e) { // 捕获4xx、5xx类HTTP错误,返回实际状态码 return e.getRawStatusCode(); } catch (Exception e) { // 捕获网络不通、连接超时、DNS解析失败等问题,返回-1标识请求失败 return -1; } } public List<Endpoints> getEndpoints() { int statusCode = myServicePinger("http://www.google.com/"); return List.of(new Endpoints("google.com", statusCode)); } }
补充说明:如果你的运行环境无法正常连接google.com,方法会返回-1标识请求失败,不会再触发崩溃。如果需要区分不同的失败场景,可以自定义不同的错误码对应不同的异常类型。
内容的提问来源于stack exchange,提问作者Chilled Shark
相关产品推荐
相关产品推荐

