下面是详细讲解“解决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技术站