解决Feign获取异常信息的处理方案

下面是详细讲解“解决Feign获取异常信息的处理方案”的攻略。

背景

Feign是一个声明式Web服务客户端,通过使用注解提供了对Ribbon和Eureka的支持,同时也支持可拔插式的编码器和解码器。在Feign中,当我们调用远程服务时,如果服务端发生异常,Feign框架只会抛出feign.RetryableException异常,这对我们排查问题十分不方便,因此我们需要一种方式来获取服务端的异常信息。

解决方案

方案一:自定义Decoder

我们可以通过自定义Feign的解码器来获取服务端返回的异常信息,具体步骤如下:

1. 自定义Decoder

import feign.Response;
import feign.codec.ErrorDecoder;

public class CustomErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        //在这里处理服务端返回的异常信息
        return new RuntimeException("服务端返回异常");
    }
}

2. 将自定义Decoder注册到Feign中

import feign.Logger;
import feign.Request;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.netflix.feign.FeignClientsConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ConditionalOnClass(Feign.class)
@Import(FeignClientsConfiguration.class)
public class FeignConfig {

    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }

    @Bean
    public Request.Options options() {
        return new Request.Options(5000, 5000);
    }

    // 注册自定义Decoder
    @Bean
    public Decoder feignDecoder() {
        return new CustomDecoder();
    }

    @Bean
    public Encoder feignEncoder() {
        return new JacksonEncoder();
    }

    // 注册自定义ErrorDecoder
    @Bean
    public ErrorDecoder feignErrorDecoder() {
        return new CustomErrorDecoder();
    }
}

现在,当我们调用远程服务时,如果服务端发生异常,自定义的CustomErrorDecoder会处理服务端返回的异常信息。

方案二:用feign原生方法获取异常信息

除了自定义Decoder以外,还有一种Feign提供的原生方法获取异常信息,具体步骤如下:

import feign.FeignException;
import feign.Response;
import feign.codec.ErrorDecoder;

public class FeignErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        try {
            String body = Util.toString(response.body().asReader());
            return new RuntimeException(body);
        } catch (IOException e) {
            return new FeignException(response.status(), response.reason(), response.request().httpMethod(), e, response.request());
        }
    }
}

在调用远程服务的地方,我们可以在catch块中通过getResult()方法获取异常信息。

try {
    result = service.remoteCall();
} catch (Exception e) {
    String errorMsg = "";
    if (e instanceof FeignException) {
        errorMsg = ((FeignException) e).getMessage();
    }
    //处理异常信息
}

示例说明

示例一:自定义Decoder获取异常信息

假如我们在服务端添加了以下代码,会抛出一个异常信息:

@GetMapping("/exception")
public String exception() {
    throw new RuntimeException("test exception");
}

客户端通过Feign调用该服务:

@Service
@FeignClient(value = "server", configuration = FeignConfig.class)
public interface FeignService {

    @GetMapping("/exception")
    String getException();

}

在自定义Decoder中获取异常信息:

public class CustomErrorDecoder implements ErrorDecoder {

    @Override
    public Exception decode(String methodKey, Response response) {
        try {
            String body = Util.toString(response.body().asReader());
            return new RuntimeException(body);
        } catch (IOException e) {
            return new FeignException(response.status(), response.reason(), response.request().httpMethod(), e, response.request());
        }
    }
}

当我们调用getException()方法时,会抛出一个RuntimeException异常,异常信息为test exception

示例二:原生方法获取异常信息

下面是一个使用原生方法获取异常信息的示例代码:

@Service
@FeignClient(value = "server", configuration = FeignConfig.class)
public interface FeignService {

    @GetMapping("/exception")
    String getException();

}

//客户端调用
try {
    String result = feignService.getException();
} catch (Exception e) {
    String errorMsg = "";
    if (e instanceof FeignException) {
        errorMsg = ((FeignException) e).getMessage();
    }
    //处理异常信息
}

当我们调用getException()方法时,如果服务器返回了错误信息,我们可以通过((FeignException) e).getMessage()方法获取异常信息。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解决Feign获取异常信息的处理方案 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • JSP页面间传值问题实例简析

    下面是对JSP页面间传值问题实例简析的完整攻略: 1. 问题分析 在使用JSP进行web页面开发的过程中,经常需要使用多个JSP页面来完成相应的业务功能,这时候我们就需要在不同的JSP页面之间传递参数或对象。 JSP页面间传值的情景: 当我们在JSP页面中调用另外一个JSP页面或Servlet时,可能需要将当前页面中的某些数据传递给其它页面或Servlet进…

    Java 2023年6月15日
    00
  • 两个例子了解java中的回调机制

    回调(Callback)是指A调用B的某个方法,B完成这个方法后通知A,这个机制在Java中被广泛应用,比如事件驱动(Event-Driven)编程、异步编程等。 下面分别通过两个实际例子来阐述Java中的回调机制: 例子一:事件驱动编程 在GUI(Graphical User Interface)编程中,事件驱动模型非常常见,我们可以通过按钮、文本框等控件…

    Java 2023年5月30日
    00
  • Java开发中的23种设计模式详解(推荐)

    Java开发中的23种设计模式详解(推荐) 1. 设计模式的介绍 设计模式是一套反复出现的解决问题的经验总结,它们是经过长期实践而形成的,在软件开发中得到了广泛应用。设计模式是一种表达解决问题和实现系统构架的能力。 2. 常用的设计模式 Java的23种设计模式可分为三类:创建型模式、结构型模式和行为型模式。 2.1 创建型模式 创建型模式主要负责对象的创建…

    Java 2023年5月19日
    00
  • Java Stream流的常见生成和操作方法总结

    Java Stream流的常见生成和操作方法总结 生成Stream流的常见方式 1. 通过Collection接口生成 可以通过Collection接口提供的stream()和parallelStream()方法生成一个Stream或ParallelStream流: List<String> list = Arrays.asList("…

    Java 2023年5月26日
    00
  • SpringBoot 集成 activiti的示例代码

    以下是Spring Boot集成Activiti的示例代码攻略: 添加依赖项 首先,我们需要在pom.xml文件中添加Activiti和Spring Boot Starter依赖项: <dependency> <groupId>org.activiti</groupId> <artifactId>activit…

    Java 2023年5月14日
    00
  • Spring Security 密码验证动态加盐的验证处理方法

    针对“Spring Security 密码验证动态加盐的验证处理方法”的完整攻略,我将分为以下几个部分进行讲解: 加盐的原理及作用 Spring Security 密码验证流程 实现动态加盐的验证处理方法 示例代码和测试 1. 加盐的原理及作用 在密码存储中,加盐是一种常用的安全策略,其原理是在密码明文前后添加一段随机的字符串(即盐),然后对整个字符串进行哈…

    Java 2023年5月20日
    00
  • springmvc模式的上传和下载实现解析

    下面我来详细讲解一下“springmvc模式的上传和下载实现解析”的完整攻略。 一、SpringMVC框架概述 SpringMVC是基于Java的前端MVC框架,它是Spring框架的一部分,主要用于Web应用程序的开发。SpringMVC分析请求并根据请求选择适当的控制器(Controller),最终生成响应结果。 二、SpringMVC模式的文件上传实现…

    Java 2023年6月15日
    00
  • 基于slf4j日志MDC输出格式的问题

    针对”基于slf4j日志MDC输出格式的问题”,我会给出完整的攻略如下: 什么是MDC? 在程序日志输出中,MDC是最常用的工具之一,全称是Mapped Diagnostic Context,它的功能是为日志输出提供上下文信息,可以理解为是一种线程级别的context。通常情况下,我们可以使用MDC来输出一些和程序运行情况相关的信息,比如用户ID、IP地址等…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部