关注点分离之RestTemplate的错误处理
作者:JackieTang
来源:生活点亮技术
1. 概览
在这个简短的教程中,将讨论如何实现一个自定义ResponseErrorHandler类并将其注入到RestTemplate实例中去,这样我们就可以在调用远程API时优雅地处理HTTP错误。
2. 默认的错误处理器
默认情况下,如果出现HTTP错误,RestTemplate将抛出下面所列的某一个异常:
HttpClientErrorException –如果HTTP状态码为4 xx
HttpServerErrorException –如果HTTP状态码为5xx
UnknownHttpStatusCodeException –如果是一个未知的HTTP状态码
所有上面的异常类都继承了RestClientResponseException。
显然,添加自定义错误处理的最简单策略,是将调用逻辑嵌在try/catch块中。然后,我们根据需要,来处理捕获的异常。
但是,如果远程API的个数增加或单个API被多个地方调用,相应的try/catch块也会随之增加,即这个简单的策略并不具有很好的扩展性。如果我们所有的远程调用都复用一个错误处理器,那就会更高效。
3. 实现一个自定义ResponseErrorHandler
根据上面的需求,我们下面要实现的自定义ResponseErrorHandler,应该能够从响应中读取HTTP状态,并且:
抛出一个对我们的应用程序有意义的异常
简单处理,即直接忽略HTTP状态码,并让响应流连续不中断
并且,实现ResponseErrorHandler接口的自定义处理器需要注入到RestTemplate实例中。 具体而言,我们需要使用RestTemplateBuilder来构建RestTemplate,并在响应流中替换DefaultResponseErrorHandler。
那么,让我们先来创建一个自定义处理器RestTemplateResponseErrorHandler吧:
@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类:
@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状态码来测试这个自定义处理器:
@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上找到。
原文链接:https://www.baeldung.com/spring-rest-template-error-handling
作者: baeldung
译者:helloworldtang
-END-
近期热文:
Swagger中配置了@ApiModelProperty的allowableValues属性但不显示的问题
为什么Kafka中的分区数只能增加不能减少?
一文带你吃透线程池
设计一个百万级的消息推送系统
Hmily:高性能异步分布式事务TCC框架
并行化:你的高并发大杀器
Spring Boot整合 Sentry 监控项目日志
重磅:Elasticsearch上市!市值近50亿美元
利用SPRING管理热加载的GROOVY对象!
Spring Boot中如何扩展XML请求和响应的支持
Java 11正式发布,新特性解读
关注我
点击“阅读原文”,看本号其他精彩内容
关注点分离之RestTemplate的错误处理相关推荐
- 社区首款 OAM 可视化平台发布!关注点分离、用户友好、上手难度低
作者 | 徐运元,杭州谐云科技合伙人及资深架构师,云计算行业和 Kubernetes 生态资深从业者 **导读:**什么是 OAM?2019 年 10 月 17 日,阿里巴巴合伙人.阿里云智能基础产品 ...
- 应用题分析思路--关注点分离
应用题分析思路–关注点分离 @(概率论) 在求解应用型概率题时,常常会因为模型尚未建立,关注点放在了概率求解上,二者交织在一起就很难厘清问题,因此拿出来强调一下. 一商店经销某种商品,每周进货量X与顾 ...
- 关注点分离与单一职责
关注点分离(separation of concerns,SOC)是对只与"特定概念.目标"(关注点)相关联的软件组成部分进行"标识.封装和操纵"的能力,即标识 ...
- 【软件架构】4+2 Layered Architecture 4+2分层架构:软件架构中的关注点分离
目录 4+2 Layered Architecture 4+2分层架构 Separation of Concerns Applied to Software Architecture软件架构中的关注点 ...
- 使用Consul做服务发现的若干姿势
作者:波斯码 来源:http://blog.bossma.cn/consul/consul-service-register-and-discovery-style/?hmsr=toutiao.io& ...
- zookeeper-一个关于paxos的故事
作者:大叔据 来源:大叔据 先讲一个故事. 从前,在国王Leslie Lamport的统治下,有个黑暗的希腊城邦叫paxos.城邦里有3类人, 决策者 提议者 群众 虽然这是一个黑暗的城邦但是很民主, ...
- 从面试官的角度谈谈大数据面试
作者:大叔据 来源:大叔据 关于传授面试经验的文章太多了,眼花缭乱,我这里就不谈了,点进来想获取几吨面试学习资料的同学,抱歉让你失望了.(我是真的找不到那么多资料...).所以,今天我们只聊面试官. ...
- 为什么 Spring 框架如此流行?
作者:shirehappy 来源:SpringForAll社区 想要学习更多关于Spring框架在Java开发者中如此流行?看这篇文章可以学到更多! 1.Spring框架特性 Spring是用于应用开 ...
- 如何健壮你的后端服务?
作者: Ali猿来如此 来源:服务端思维 对每一个程序员而言,故障都是悬在头上的达摩克利斯之剑,都唯恐避之不及,如何避免故障是每一个程序员都在苦苦追寻希望解决的问题.对于这一问题,大家都可以从需求分析 ...
最新文章
- orm连接mysql_Django项目如何使用ORM连接MySQL
- 54. Leetcode 113. 路径总和 II (二叉树-二叉树路径和)
- 类与类之间关系,用C#和JavaScript体现
- 高射炮打蚊子,杀鸡用绝世好剑:在SAP Kyma上运行UI5应用
- centos一键清理磁盘空间_docker越来越大,心慌,清理一波吧
- PyTorch官方教程中文版:PYTORCH之60MIN入门教程代码学习
- python智能工厂_智能工厂关键技术应用 第八讲 智能工厂的Python编程应用
- ReentrantLock1.8源码
- Linux命令行学习日志-ps ax
- 如此轻松就能搭建聊天机器人,我也要弄一个~
- 机器学习入门-用Java实现简单感知机
- SpringBoot使用Ehcache
- android音频系统(4):AudioService之音量管理
- 华为ENSP之出口网关设备故障vrrp快速切换
- getPhoneNumber:fail Error: 用户绑定的手机需要进行验证,请在客户端完成短信验证
- chrome 插件 click 无效
- 一个Flash开发者从入门到放弃的成长之路
- 系统运维工程师装逼完全指南
- python文件路径path
- java学习之路8——Java集合框架
热门文章
- c/c++ ide 简介
- linux redis WARNING overcommit_memory is set to 0! 解决方案
- linux 内核 链表 list_head 使用方法
- pow函数gcc编译提示 undefined reference to `power' 的解决办法
- nginx+lua 配置302 不改写白名单哈希表
- C语言中, include 和 include 的区别和注意点
- html 表单自动数值,web前端学习技术之对HTML5 智能表单的理解
- java ee中javamail注解_JavaEE之注解
- mysql bigint 运算_mysql中int、bigint、smallint 和 tinyint的区别详细介绍
- 关不关机 扫地机器人_BOBOT扫地机器人能扫还能拖,你的家庭好助理