Spring Cloud Feign 自定义配置(重试、拦截与错误码处理) 实践

人在魔都,目前为贝壳做事,本篇文章主要分享下 Feign 自定义配置的工程实践,希望你们可以找到些有用的东西,文章已被公众号收录

基于 spring-boot-starter-parent 2.1.9.RELEASE, spring-cloud-openfeign 2.1.3.RELEASE

引子

Feign 是一个声明式、模板化的HTTP客户端,简化了系统发起Http请求。创建它时,只需要创建一个接口,然后加上FeignClient注解,使用它时,就像调用本地方法一样,作为开发者的我们完全感知不到这是在调用远程的方法,也感知不到背后发起了HTTP请求:

/**
* @author axin
* @suammry xx 客户端
*/
@FeignClient(value = "xxClient",url = "${xx.host:www.axin.com}")
public interface DemoClient { @PostMapping(value = "/xxx/url", headers = "Content-Type=application/json"})
yourResponse requestHTTP(@RequestBody JSONObject param); }

上述的代码就是一个定义一个Feign HTTP 客户端,在其他类中只需要 @Autowired DemoClient,就可以像调用本地方法一样发起HTTP请求。

介绍就到这,接下来进入主题,因为 FeignClient 将发起HTTP请求与解析返回报文都做了包装,如果你的业务场景需要定制一些调用机制,比如:

  1. 我想在发起请求响应超时失败时自动重试 —— 自定义重试机制
  2. 我想单独对某些异常的HTTP状态码特殊处理 —— 自定义ErrorDecoder
  3. 服务端接口需要验证签名,所以我方在发起请求时要生成签名然后传过去 —— 定义 Fegin 拦截器

基于此,本文就以上述3个需求场景为例来介绍如何自定义 FeignClient 的配置

FeignClient的默认配置类

Feign Client 默认的配置类为 FeignClientsConfiguration, 这个类在 spring-cloud-netflix-core 的 jar 包下。

默认注入了很多 Feign 相关的配置Bean,包括FeignRetryer、 FeignLoggerFactory 和 FormattingConversionService 等。另外,Decoder、Encoder和 Contract 这3个类在没有Bean被注入的情况下,会自动注入默认配置的 Bean,即ResponseEntity Decoder、SpringEncoder 和 SpringMvcContract。

如果你不知道如何自己定义配置时,不放点进去看看人家默认配置是如何实现的。这里就不晒源码了。

FeignClient 注解参数

每个注解参数都做了注释,详情请见下方源码:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FeignClient { /**
* 指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
*/
@AliasFor("name")
String value() default "";
@Deprecated
String serviceId() default "";
@AliasFor("value")
String name() default ""; /**
* Sets the <code>@Qualifier</code> value for the feign client.
* 这个bean在应用上下文中的名字为接口的全限定名,你也可以使用 @FeignClient 注解中的 qualifier 属性给bean指定一个别名
*/
String qualifier() default ""; /**
* url地址
*/
String url() default ""; /**
* 当发生404错误,如果该字段为true,会调用decoder进行解码,否则抛出FeignException
*/
boolean decode404() default false; /**
* 指定FeignClient 的配置类,优先级最高,默认的配置类为 FeignClientsConfiguration类
*/
Class<?>[] configuration() default {}; /**
* 配置熔断器的处理类
*/
Class<?> fallback() default void.class; /**
* 工厂类,用于生产fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复代码
*/
Class<?> fallbackFactory() default void.class; /**
* 定义统一的路径前缀
*/
String path() default ""; /**
* Whether to mark the feign proxy as a primary bean. Defaults to true.
*/
boolean primary() default true;
}

自定义Feign配置类

在 Spring Cloud 中,你可以通过 @FeignClient 注解声明额外的配置(比 FeignClientsConfiguration 级别高)去控制feign客户端,以一开始的feign接口为例:

/**
* @author axin
* @suammry xx 客户端
*/
@FeignClient(value = "xxClient",url = "${xx.host:www.axin.com}",configuration = MyConfiguration.class)
public interface DemoClient { @PostMapping(value = "/xxx/url", headers = "Content-Type=application/json"})
yourResponse requestHTTP(@RequestBody JSONObject param);
}

在上面这个示例中,feign客户端在MyConfiguration中的配置将会覆盖FeignClientsConfiguration中的配置。

要注意的是: MyConfiguration不需要使用@Configuration注解。如果加上了,它将全局生效

Retryer-重试机制的自定义

/**
* @author axin
* @summary fegin 客户端的自定义配置
*/
public class MyConfiguration { /**
* 自定义重试机制
* @return
*/
@Bean
public Retryer feignRetryer() {
//fegin提供的默认实现,最大请求次数为5,初始间隔时间为100ms,下次间隔时间1.5倍递增,重试间最大间隔时间为1s,
return new Retryer.Default();
}
}

ErrorDecoder-错误解码器的自定义

当feign调用返回HTTP报文时,会触发这个方法,方法内可以获得HTTP状态码,可以用来定制一些处理逻辑等等。

/**
* @author axin
* @summary fegin 客户端的自定义配置
*/
@Slf4j
public class MyConfiguration { /**
* 自定义重试机制
* @return
*/
@Bean
public Retryer feignRetryer() {
//最大请求次数为5,初始间隔时间为100ms,下次间隔时间1.5倍递增,重试间最大间隔时间为1s,
return new Retryer.Default();
} @Bean
public ErrorDecoder feignError() {
return (key, response) -> {
if (response.status() == 400) {
log.error("请求xxx服务400参数错误,返回:{}", response.body());
} if (response.status() == 409) {
log.error("请求xxx服务409异常,返回:{}", response.body());
} if (response.status() == 404) {
log.error("请求xxx服务404异常,返回:{}", response.body());
} // 其他异常交给Default去解码处理
// 这里使用单例即可,Default不用每次都去new
return new ErrorDecoder.Default().decode(key, response);
};
} }

采用了lambda的写法,response变量是Response类型,通过status()方法可以拿到返回的HTTP状态码,body()可以获得到响应报文。

Feign拦截器实践

拦截器在请求发出之前执行,在拦截器代码里可以修改请求参数,header等等,如果你有签名生成的需求,可以放在拦截器中来实现

/**
* @author axin
* @summary fegin 客户端的自定义配置
*/
@Slf4j
public class MyConfiguration { /**
* 自定义重试机制
* @return
*/
@Bean
public Retryer feignRetryer() {
//最大请求次数为5,初始间隔时间为100ms,下次间隔时间1.5倍递增,重试间最大间隔时间为1s,
return new Retryer.Default();
} @Bean
public ErrorDecoder feignError() {
return (key, response) -> {
if (response.status() == 400) {
log.error("请求xxx服务400参数错误,返回:{}", response.body());
} if (response.status() == 409) {
log.error("请求xxx服务409异常,返回:{}", response.body());
} if (response.status() == 404) {
log.error("请求xxx服务404异常,返回:{}", response.body());
} // 其他异常交给Default去解码处理
// 这里使用单例即可,Default不用每次都去new
return new ErrorDecoder.Default().decode(key, response);
};
} /**
* fegin 拦截器
* @return
*/
@Bean
public RequestInterceptor cameraSign() {
return template -> { // 如果是get请求
if (template.method().equals(Request.HttpMethod.GET.name())) {
//获取到get请求的参数
Map<String, Collection<String>> queries = template.queries();
} //如果是Post请求
if (template.method().equals(Request.HttpMethod.POST.name())) {
//获得请求body
String body = template.requestBody().asString();
JSONPObject request = JSON.parseObject(body, JSONPObject.class);
} //Do what you want... 例如生成接口签名 String sign = "根据请求参数生成的签名";
//放入url?之后
template.query("sign", sign); //放入请求body中
String newBody = "原有body" + sign;
template.body(Request.Body.encoded(newBody.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
};
}
}

可以看到代码中给了如何获取请求参数和修改请求参数的示例。

总结

小结一下,对于开头提出的场景:

  1. 我想在发起请求响应超时失败时自动重试 —— 自定义重试机制
  2. 我想单独对某些异常的HTTP状态码特殊处理 —— 自定义ErrorDecoder
  3. 服务端接口需要验证签名,所以我方在发起请求时要生成签名然后传过去 —— 定义 Fegin 拦截器

给出了自定义 feign 配置的方式实现的样例代码,希望对你有用,如果有更好的方式简化HTTP请求,欢迎留言分享~

参考链接

Spring Cloud Feign 自定义配置(重试、拦截与错误码处理) 实践的更多相关文章

  1. 笔记:Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  2. 笔记:Spring Cloud Feign Hystrix 配置

    在 Spring Cloud Feign 中,除了引入了用户客户端负载均衡的 Spring Cloud Ribbon 之外,还引入了服务保护与容错的工具 Hystrix,默认情况下,Spring Cl ...

  3. Spring Cloud Feign Ribbon 配置

    由于 Spring Cloud Feign 的客户端负载均衡是通过 Spring Cloud Ribbon 实现的,所以我们可以直接通过配置 Ribbon 的客户端的方式来自定义各个服务客户端调用的参 ...

  4. 笔记:Spring Cloud Feign 其他配置

    请求压缩 Spring Cloud Feign 支持对请求与响应进行GZIP压缩,以减少通信过程中的性能损耗,我们只需要通过下面二个参数设置,就能开启请求与响应的压缩功能,yml配置格式如下: fei ...

  5. Spring Cloud Feign 声明式服务调用

    目录 一.Feign是什么? 二.Feign的快速搭建 三.Feign的几种姿态 参数绑定 继承特性 四.其他配置 Ribbon 配置 Hystrix 配置 一.Feign是什么? ​ 通过对前面Sp ...

  6. Spring Cloud Feign 在调用接口类上,配置熔断 fallback后,输出异常

    Spring Cloud Feign 在调用接口类上,配置熔断 fallback后,出现请求异常时,会进入熔断处理,但是不会抛出异常信息. 经过以下配置,可以抛出异常: 将原有ErrorEncoder ...

  7. 微服务架构之spring cloud feign

    在spring cloud ribbon中我们用RestTemplate实现了服务调用,可以看到我们还是需要配置服务名称,调用的方法 等等,其实spring cloud提供了更优雅的服务调用方式,就是 ...

  8. Spring cloud Feign 深度学习与应用

    简介 Spring Cloud Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单.Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解 ...

  9. spring coud Feign常用配置

    Ribbon配置 在Feign中配置Ribbon非常简单,直接在application.properties中配置即可,如: # 设置连接超时时间 ribbon.ConnectTimeout=500 ...

随机推荐

  1. math库常用函数

  2. Python Tuple(元组) min()方法

    描述 Python 元组 min() 函数返回元组中元素最小值.高佣联盟 www.cgewang.com 语法 min()方法语法: min(tuple) 参数 tuple -- 指定的元组. 返回值 ...

  3. electron开发 - 打印流程(仅支持6.0.0版本以上)

    Electron打印 标签打印 标签打印一般有两种方式: 驱动打印,与普通打印机一样通过驱动方式打印. 通过指令打印,不同厂家的的打印机指令集不一样,可查看厂家提供的手册. electron 打印方式 ...

  4. 数据库Schema

    在学习SQL的过程中,会遇到一个让你迷糊的Schema的概念.实际上,schema就是数据库对象的集合,这个集合包含了各种对象如:表.视图.存储过程.索引等.为了区分不同的集合,就需要给不同的集合起不 ...

  5. 虚拟机安装Centos(VirtulBox)

    阿里云服务器本月底到期了,之前自己犹豫不觉没上279元3年服务器的车,但是又要用linux,所以有了这篇文章. VirtulBox 一款开源的虚拟化主机应用,可以实现一台电脑上运行多个操作系统(Lin ...

  6. 【java提高】(19)---BigDecimal详解和精度问题

    BigDecimal详解和精度问题 一.背景 在实际开发中,对于 不需要任何准确计算精度的属性可以直接使用float或double,但是如果需要精确计算结果,则必须使用BigDecimal,例如价格. ...

  7. swift基础_ set get方法 理解

    swift中重写set get方法是这样的. 先定义一个变量,当调用set方法的时候,系统会有一个newValue, 将newValue赋值给我们定义的变量,然后从get方法返回去. swift中一般 ...

  8. python7.3客户端、服务端的建立

    import socket #创建客户端client=socket.socket() #生成socket连接对象client.connect("localhost",6969) # ...

  9. Unity 笔记

    摄像机 Main Camera 跟随主角移动,不看 UI 剧情摄像机 当进入剧情时,可以关闭 main camera,启用剧情摄像机,不看 UI UI 摄像机 看 UI Unity编辑器常用的sett ...

  10. NMS系列

    NMS soft NMS softer NMS https://www.cnblogs.com/VincentLee/p/12579756.html