当我们使用 RestTemplate 发送请求时, 如果接口返回的不是 200 状态(而是 4xx、5xx 这样的异常状态),则会抛出异常报错。

但在实际接口对接中,我们可能希望获取接口返回的异常信息并返回(比如返回到前端)。这个可以通过自定义 RestTemplate 异常的处理来实现,下面通过样例进行演示。
十、请求异常处理
1,简单的样例代码
(1)首先我们需要创建一个自己的异常处理控制器(ExceptionHandler 类),该类实现 ResponseErrorHandler 接口。
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
RestTemplate restTemplate = new RestTemplate(factory);
//Response status code 4XX or 5XX to the client.
restTemplate.setErrorHandler(new RestThrowErrorHandler());
return restTemplate;
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(15000); // 连接超时
factory.setReadTimeout(5000); // 数据读取超时时间
return factory;
}
}(3)最后是一个简单的请求样例。经过上面设置后,无论请求成功或者失败都会返回(不会抛异常),所以我们需要通过状态码来判断请求是否成功。
@RestController
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/test")
public String test() {
String url = "http://localhost:8080/xxxxxx";
ResponseEntity responseEntity = restTemplate.getForEntity(url, String.class);
// 判断请求是否发生异常
if(!responseEntity.getStatusCode().is2xxSuccessful()){
// 返回异常信息
return "请求失败,异常信息:" + responseEntity.getBody();
}
// 没有异常的话则返回正常的响应结果
return responseEntity.getBody();
}
} (4)由于代码中我们请求了一个不存在的接口,并且在请求失败时将错误信息返回到前端,因此前端会显示如下内容:
2,代码改进
(1)通常来说我们不会直接把业务代码写在 Controller 里,而是通过 Service 实现。首先我们创建一个 Service,里面调用 RestTemplate 进行网络请求,当请求异常时直接抛出异常。
@Service
public class UserService {
@Autowired
private RestTemplate restTemplate;
public String getInfo() {
String url = "http://localhost:8080/xxxxxx";
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
// 判断请求是否发生异常
if(!responseEntity.getStatusCode().is2xxSuccessful()){
// 抛出异常
throw new RestClientException(responseEntity.getBody());
}
// 没有异常的话则返回正常的响应结果
return responseEntity.getBody();
}
}(2)Controller 这边很简单,就是调用 Service 发起请求,然后返回结果。
@RestController
public class HelloController {
@Autowired
private UserService userService;
@GetMapping("/test")
public String test() {
return userService.getInfo();
}
}(3)由于前面 Service 中我们将异常抛出了,所以要定义一个全局的异常处理类,捕获这个异常,并返回给前端处理的结果。
关于全局异常处理更详细用法可以参考我之前写的文章:
@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(RestClientException.class)
public ResponseEntity throwRestException(RestClientException restClientException){
return new ResponseEntity(restClientException.getMessage(),
HttpStatus.BAD_REQUEST);
}
} (4)测试一下,可以看到异常信息已经返回到前端页面。

