一、异常现象

在 JAVA 开发中我们经常会使用RestTemplate进行远程接口调用,如果请求的接口出现异常:超时、服务不存在等等情况,这时响应状态不是200,而是400、500等等状态码,这种情况下,程序便会抛出异常,如下:

restTemplate 504 resttemplate 504错误_restTemplate 504

404异常

上面出现的异常我是模拟出来的,由“/postss/1”替换了正确的地址由“/posts/1”。这时请求该服务不存在,肯定会抛出404异常。代码如下:

restTemplate 504 resttemplate 504错误_异常处理_02

这里抛出了404 Not Found 的异常,后面的业务逻辑肯定是无法执行的了。

我们在实际的开发中,不管服务端因为什么问题导致异常,都应该获得最终的请求结果(HTTP请求结果状态400、500),而不是获得一个抛出的异常。

二、源码解析-默认实现

首先程序中99%的异常都是可以自定义处理的,RestTemplate请求结果的异常自然也是可以自定义处理的。在开始自定义之前,我们来探究一下异常的默认处理实现,以此来说明为什么会出现这样的现象?

RestTemplate请求结果的异常处理器接口是ResponseErrorHandler,下面介绍一下该接口的两个重要方法:hasError():用于判断HttpResponse是否是异常响应(通过状态码)handleError():用于处理异常响应结果(非200状态码段)DefaultResponseErrorHandler是ResponseErrorHandler的默认实现下面是ResponseErrorHandler接口的源码实现:

restTemplate 504 resttemplate 504错误_状态码_03

上面提到ResponseErrorHandler的默认实现是DefaultResponseErrorHandler,既然如此我们跟踪一下该实现看看是如何来处理异常响应的?从HttpResponse解析出Http StatusCode,如果状态码StatusCode为null,就抛出UnknownHttpStatusCodeException异常。

restTemplate 504 resttemplate 504错误_状态码_04

如果StatusCode存在,就会调用DefaultResponseErrorHandler#handleError(ClientHttpResponse, HttpStatus)接口来解析出StatusCode的series,也就是状态码段(除了200段,其他全是异常状态码),解析规则是StatusCode/100取整。

restTemplate 504 resttemplate 504错误_自定义_05

进一步针对客户端异常和服务端异常进行处理,处理的方法是抛出HttpClientErrorException。

restTemplate 504 resttemplate 504错误_java template error_06

三、RestTemplate自定义异常处理

通过上面的介绍可知:要实现RestTemplate自定义异常处理,只需要实现ResponseErrorHandler 接口就可以。方法如下:

restTemplate 504 resttemplate 504错误_restTemplate 504_07

将MyRestErrorHandler 在RestTemplate实例化的时候进行注册,这样请求的异常处理便会走自定义的异常处理类进行处理了。实现方式如下:

restTemplate 504 resttemplate 504错误_java template error_08

这时再去执行第一小节中的示例代码,就不会抛出异常。而是得到一个HTTP Status 404的结果。我们可以根据这个结果,在程序中继续向下执行代码。

restTemplate 504 resttemplate 504错误_自定义_09

到此已经介绍完RestTemplate请求异常处理逻辑,欢迎大家在评论区踊跃发言,各抒自见,共同交流学习,也欢迎大家对本文中错误或者不足之处提出您的宝贵意见!