前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关注点分离之RestTemplate的错误处理

关注点分离之RestTemplate的错误处理

作者头像
烟雨平生
发布2023-03-07 16:32:20
5800
发布2023-03-07 16:32:20
举报
文章被收录于专栏:数字化之路数字化之路
原文链接:https://www.baeldung.com/spring-rest-template-error-handling

作者: baeldung

译者:helloworldtang

1. 概览

在这个简短的教程中,将讨论如何实现一个自定义ResponseErrorHandler类并将其注入到RestTemplate实例中去,这样我们就可以在调用远程API时优雅地处理HTTP错误。

2. 默认的错误处理器

默认情况下,如果出现HTTP错误,RestTemplate将抛出下面所列的某一个异常:

  1. HttpClientErrorException –如果HTTP状态码为4 xx
  2. HttpServerErrorException –如果HTTP状态码为5xx
  3. UnknownHttpStatusCodeException –如果是一个未知的HTTP状态码

所有上面的异常类都继承了RestClientResponseException。

显然,添加自定义错误处理的最简单策略,是将调用逻辑嵌在try/catch块中。然后,我们根据需要,来处理捕获的异常。

但是,如果远程API的个数增加或单个API被多个地方调用,相应的try/catch块也会随之增加,即这个简单的策略并不具有很好的扩展性。如果我们所有的远程调用都复用一个错误处理器,那就会更高效。

3. 实现一个自定义ResponseErrorHandler

根据上面的需求,我们下面要实现的自定义ResponseErrorHandler,应该能够从响应中读取HTTP状态,并且:

  1. 抛出一个对我们的应用程序有意义的异常
  2. 简单处理,即直接忽略HTTP状态码,并让响应流连续不中断

并且,实现ResponseErrorHandler接口的自定义处理器需要注入到RestTemplate实例中。 具体而言,我们需要使用RestTemplateBuilder来构建RestTemplate,并在响应流中替换DefaultResponseErrorHandler。

那么,让我们先来创建一个自定义处理器RestTemplateResponseErrorHandler吧:

代码语言:javascript
复制
@Component
public class RestTemplateResponseErrorHandler 
  implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse httpResponse) 
      throws IOException {

        return (
          httpResponse.getStatusCode().series() == CLIENT_ERROR 
          || httpResponse.getStatusCode().series() == SERVER_ERROR);
    }

    @Override
    public void handleError(ClientHttpResponse httpResponse) 
      throws IOException {

        if (httpResponse.getStatusCode()
          .series() == HttpStatus.Series.SERVER_ERROR) {
            // handle SERVER_ERROR
        } else if (httpResponse.getStatusCode()
          .series() == HttpStatus.Series.CLIENT_ERROR) {
            // handle CLIENT_ERROR
            if (httpResponse.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new NotFoundException();
            }
        }
    }
}

接下来,我们使用RestTemplateBuilder来初始化RestTemplate实例,这样就可以加载前面创建的RestTemplateResponseErrorHandler类:

代码语言:javascript
复制
@Service
public class BarConsumerService {

    private RestTemplate restTemplate;

    @Autowired
    public BarConsumerService(RestTemplateBuilder restTemplateBuilder) {
        RestTemplate restTemplate = restTemplateBuilder
          .errorHandler(new RestTemplateResponseErrorHandler())
          .build();
    }

    public Bar fetchBarById(String barId) {
        return restTemplate.getForObject("/bars/4242", Bar.class);
    }

}

4. 测试处理器

最后,让我们通过mock一个服务器,并让服务器返回一个NOT_FOUND HTTP状态码来测试这个自定义处理器:

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { NotFoundException.class, Bar.class })
@RestClientTest
public class RestTemplateResponseErrorHandlerIntegrationTest {

    @Autowired
    private MockRestServiceServer server;

    @Autowired
    private RestTemplateBuilder builder;

    @Test(expected = NotFoundException.class)
    public void  givenRemoteApiCall_when404Error_thenThrowNotFound() {
        Assert.assertNotNull(this.builder);
        Assert.assertNotNull(this.server);

        RestTemplate restTemplate = this.builder
          .errorHandler(new RestTemplateResponseErrorHandler())
          .build();

        this.server
          .expect(ExpectedCount.once(), requestTo("/bars/4242"))
          .andExpect(method(HttpMethod.GET))
          .andRespond(withStatus(HttpStatus.NOT_FOUND));

        Bar response = restTemplate 
          .getForObject("/bars/4242", Bar.class);
        this.server.verify();
    }
}

5. 总结

本文提供了一个解决方案,用于实现和测试RestTemplate的自定义错误处理器,该处理器可以将HTTP错误转换为有意义的异常。

与往常一样,本文中提供的代码可以在Github上找到。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概览
  • 2. 默认的错误处理器
  • 3. 实现一个自定义ResponseErrorHandler
  • 4. 测试处理器
  • 5. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档