当我们使用 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"; ResponseEntityresponseEntity = 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 ResponseEntitythrowRestException(RestClientException restClientException){ return new ResponseEntity (restClientException.getMessage(), HttpStatus.BAD_REQUEST); } }
(4)测试一下,可以看到异常信息已经返回到前端页面。