ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、视频、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
除了上一节为大家介绍的异常拦截处理方式,还有另外一种异常的拦截处理方式:那就是使用Feign的ErrorDecoder进行异常信息转换。我们可以在FeignClient端的ErrorDecoder方法中将AjaxResponse转为RuntimeException抛出! ## 一、Hystrix引入的6种异常 以下6种异常是Hystrix引入的异常: | Failure Type | Exception class | Exception.cause | subject to fallback | | --- | --- | --- | --- | | FAILURE | `HystrixRuntimeException` | 程序异常underlying exception (user-controlled) | YES | | TIMEOUT | `HystrixRuntimeException` | 超时异常`j.u.c.TimeoutException` | YES | | SHORT\_CIRCUITED | `HystrixRuntimeException` | 熔断异常`j.l.RuntimeException` | YES | | THREAD\_POOL\_REJECTED | `HystrixRuntimeException` | 线程池满载拒绝异常`j.u.c.RejectedExecutionException` | YES | | SEMAPHORE\_REJECTED | `HystrixRuntimeException` | 信号量满异常`j.l.RuntimeException` | YES | | BAD\_REQUEST | HystrixBadRequestException | 请求参数错误等非系统产生的异常 | NO | * 除了HystrixBadRequestException,都会导致服务降级,也都会计入服务失败统计次数数据之内,异常多次抛出将导致服务熔断。 * **如果实现业务时有一些异常希望能够一直向上抛出,而不是触发FeignClient的Fallback 策略,便可以封装到`HystrixBadRequestException`中。** * 上面6种异常抛出之后,都会导致数据库事务回滚,因为他们都是运行时异常RuntimeException ## 二、FeignClient异常拦截与处理 ![](https://img.kancloud.cn/3a/3b/3a3b1f49e2745ce22f0c1db7762828e6_858x195.png) ### 2.1.自定义ErrorDecoder * ErrorDecoder只有在FeignClient远程服务接口响应的HTTP状态码**不是**200-300的情况下才会被执行。所以必须使用上一节介绍的HTTP状态码的方式传递异常。 * ErrorDecoder接口是Feign提供的,我们可以自定义其实现,根据“服务提供端”的HTTP响应的状态码,判断远程服务接口是否出现异常,如果出现异常抛出RuntimeException,实现异常的传递。并且不要触发FeignClient的Fallback 策略,所以抛出HystrixBadRequestException。 > 有的朋友可能会问? > > 1. 为什么不要触发FeignClient的Fallback 策略?因为我们现在需要的是RuntimeException,如果触发FeignClient的Fallback 策略就又变成“异常信息”了。“异常信息”数据是不能触发数据库事务回滚的。 > 2. 那FeignClient的Fallback 策略还有什么用?当然有用,在远程服务网络超时或服务宕机的时候,还是要依靠FeignClient的Fallback 策略。因为此时没有响应结果返回。 ~~~ @Configuration public class FeignClientErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { try { if(response.body() != null){ String jsonStr = Util.toString(response.body().asReader()); //json字符串转对象 ObjectMapper mapper = new ObjectMapper(); AjaxResponse ajaxResponse = mapper.readValue(jsonStr, AjaxResponse.class); // 将AjaxResponse包装成 HystrixBadRequestException,不会触发FeignClient的Fallback策略 if (!ajaxResponse.isIsok()) { return new HystrixBadRequestException(ajaxResponse.getMessage()); } } } catch (IOException ex) { return feign.FeignException.errorStatus(methodKey, response); } return feign.FeignException.errorStatus(methodKey, response); } } ~~~ ### 2.2.为FeignClient指定error decoder,二选一即可: * 全局配置,对所有FeignClient生效 ~~~ @EnableFeignClients( defaultConfiguration = FeignClientErrorDecoder.class ) ~~~ * 在单个的FeignClient生效 ~~~ @FeignClient(name = "ASERVICE-SMS", configuration = FeignClientErrorDecoder.class, fallback = SmsServiceFallback.class) public interface SmsService { //省略 } ~~~ 还有通过配置文件指定的方法,相对麻烦。笔者这里就不列举了! ### 2.3.在代码调用的位置拦截异常,触发数据库事务回滚 ![](https://img.kancloud.cn/a0/62/a062073925398383dddfb596e508db44_1506x684.png)