大数跨境
0
0

全面彻底掌握OpenFeign

全面彻底掌握OpenFeign Spring全家桶实战案例
2024-09-19
0
导读:全面彻底掌握OpenFeign

环境:Spring Boot3.2.5



1. 简介

OpenFeign 是一个声明式网络服务客户端,它让编写网络服务客户端变得更简单。使用 Feign 调用其他服务时,我们几乎不需要编写任何代码。我们只需创建一个接口并对其进行注解即可。它支持 OpenFeign 和 Jakarta JAX-RS 注释。

在篇文章,我们将深入 Spring Cloud OpenFeign 全方面的介绍各个知识点。

在介绍OpenFeign之前,我们先来对比下Feign vs. OpenFeign vs. Spring HttpExchange

Feign、OpenFeign 和 Spring HttpExchange 都是用于在 Java 应用程序中创建声明式 HTTP 客户端。

功能 Feign OpenFeign Spring HttpExchange
起源与目的 由 Netflix 开发 扩展自Feign,功能大大增强 Spring的一部分
Spring集成 可用于 Spring 和非 Spring 应用程序 通过Spring Cloud OpenFeign 模块集成 Spring特有
定制 可定制的组件、请求和响应 可定制的组件、请求和响应 更加细粒度的控制
社区 不太活跃 非常活跃 亲儿子,没得说
案例 微服务、RESTful API 集成 微服务、RESTful API 集成 Spring应用程序中的自定义HTTP交互

在Spring Boot项目中,个人更建议使用HttpExchange,你无需引入任何其它的依赖。不过OpenFeign 与服务发现和负载平衡等其他 Spring Cloud组件集成得很好。而 HttpExchange 使用 WebClient 来调用 HTTP 请求,因此能更好地控制请求和响应处理。

但是,OpenFeign 是基于每请求线程模型的阻塞型客户端,对于每个请求,指定的线程都会阻塞,直到收到响应为止。HttpExchange 使用的 WebClient 是非阻塞和反应式的,因此很容易克服上述性能瓶颈。

OpenFeign不支持响应式的,如果你希望基于非阻塞,那么你可以查看下面这篇文章

深入ReactiveFeign:反应式远程接口调用的最佳实践

2. 实战案例

2.1 引入依赖

<dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-openfeign</artifactId>  <version>2022.0.3</version></dependency>

注意:根据你使用的Spring Boot版本引入对应Cloud版本。

2.2 开启功能

接下来,我们需要使用 @EnableFeignClients 注解启用 Feign Clients,该注解可对所有注释为 @FeignClient 的接口进行组件扫描。

@SpringBootApplication@EnableFeignClients(basePackages="com.pack.feign")public class AppApplication {}

这里配置了basePackages属性来指定要扫描的包,如果你的注解使用在启动类上,那么你可以不用指定。

2.3 声明Feign客户端

可以使用 @FeignClient 注解将接口声明为 Feign 客户端。下面创建一个简单的客户端,获取用户列表。

@FeignClient(value = "userFeignClient", url = "http://localhost:8088")public interface UserFeignClient {
@GetMapping("/users") ResponseEntity<List<User>> getUsers() ;}

说明:

value:指定客户端的名称。必填项,可以是任意值。
url:基本请求的URL。

在getUsers方法上使用了@GetMapping声明了具体的目标接口。

2.4 接口调用

要进行接口调用非常的简单,我们只需要在需要的地方注入上面的Feign接口即可。

private final UserFeignClient userFeignClient ;public UserFeignController (UserFeignClient userFeignClient) {  this.userFeignClient = userFeignClient ;}// 接口处理ResponseEntity<List<User>> responseEntity = userFeignClient.getUsers() ;if (responseEntity.getStatusCode().is2xxSuccessful()) {  List<User> usersList = responseEntity.getBody() ;  usersList.forEach(System.out::println) ;} else if(responseEntity.getStatusCode().is4xxClientError()) {  throw new BadRequestException("Bad Request") ;} else {  throw new RuntimeException("Server Error") ;}

使用方法与普通的bean方式一样。

2.5 使用继承

为了避免模板代码,Feign 允许将常用功能归入基础接口。在下面的示例中,我们创建了一个新的 AccountFeignClient,它是从上面创建的 UserFeignClient 继承而来的。

@FeignClient(value = "accountFeignClient", url = "http://localhost:8088/")public interface AccountFeignClient extends UserFeignClient {  @GetMapping(value = "/account/{id}")  String getAccountByUser(@PathVariable("id") Long id) ;}

注意:不支持多级继承。

2.6 OpenFeign配置

  • 默认配置

每个 Feign 客户端都由一组组件组成,这些组件共同作用于远程服务调用。无论何时创建命名客户端,Spring Cloud 都会使用 FeignClientsConfiguration 为这些组件创建默认值。在该类中的大多数bean定义,我们都可以通过自定义的方式进行覆盖。

默认有:

  • Decoder:要对响应进行解码,需要使用封装了 SpringDecoder 的 ResponseEntityDecoder。

  • Encoder:SpringEncoder 用于对 RequestBody 进行编码。

  • Logger:Slf4jLogger 是 Feign 使用的默认日志记录器。

  • Contract:提供注解处理的 SpringMvcContract。

  • Feign.Builder:用于构建Feign组件

  • Retryer:当容器中不存在断路器相关依赖或为开启时,可配置重试请求的策略。

  • Client:这是全局的,用来处理请求。

接下来,详细讲解自定义的配置。

  • 自定义配置

Spring Cloud 允许我们通过指定附加配置,用来覆盖 FeignClientsConfiguration 中的默认bean配置。

如下,覆盖 AccountFeignClient 中的默认 HttpClient,使用 ApacheHttp5Client。我们需要创建一个配置类 AccountFeignConfiguration 并声明客户端 bean。

public class PackAccountFeignConfiguration {  @Bean  public CloseableHttpClient feignClient() {    return HttpClients.createDefault() ;  }}

接下来,可以在@FeignClient注解中如下定义

@FeignClient(  value = "accountFeignClient",  url = "http://localhost:8088/",  configuration = PackAccountFeignConfiguration.class)public interface AccountFeignClient extends UserFeignClient {}

通过configuration属性指定我们自定义的配置。你还需要引入下面的依赖

<dependency>  <groupId>io.github.openfeign</groupId>  <artifactId>feign-hc5</artifactId></dependency>

如果你使用okhttp,那么也请引入对应的依赖即可。

  • 通过配置文件配置

我们还可以使用应用程序属性覆盖配置。在这里,我们也可以为特定的 Feign 客户端或所有客户端重写配置。

如下,将所有的Feign客户端配置超时时间

spring:  cloud:    openfeign:      config:        default:          connectTimeout: 5000

同样,如果我们只想覆盖 AccountFeignClient 的超时,可以使用使用 "value "属性指定的 Feign Client 名称进行如下设置。

spring:  cloud:    openfeign:      config:        accountFeignClient:          connectTimeout: 5000

注意:如果我们同时创建 @Configuration Bean 和配置属性,属性值将优先于 @Configuration 值。我们可以通过设置 spring.cloud.openfeign.client.default-to-properties 来更改优先级。

spring:  cloud:    openfeign:      client:        default-to-properties: false

这样配置后,就不是属性值配置有限了。

  • 拦截器配置

Feign 提供了 RequestInterceptor 接口,可用于执行身份验证或日志记录等任务。

@BeanRequestInterceptor requestInterceptor() {  return requestTemplate -> {    requestTemplate.header("requestID", "UUID");  } ;}

为请求添加自定义的请求header。

  • 异常处理

Feign 的默认 ErrorDecoder 会在出现错误时抛出 FeignException。我们可以编写自己的自定义 ErrorDecoder。这样,我们就可以进行特定的错误处理。

@BeanErrorDecoder errorDecoder() {  return new ErrorDecoder() {    public Exception decode(String methodKey, Response response) {      return switch (response.status()) {        case 400 -> new BadRequestException(response) ;        case 429 -> new TooManyRequestsException(response) ;        default -> new Exception("feign client exception") ;    } ;  } ;}

在这里你可以更细粒度的根据状态来处理异常。

  • 读写超时配置

Feign 允许我们配置连接和读取超时。可以为每个客户端或所有客户端进行配置。

spring:  cloud:    openfeign:      client:        config:          default:            read-timeout: 5000            connect-timeout: 5000

这将为所有的客户端配置同样的超时时间。

  • 日志配置

默认情况下,每个 Feign 客户端都会创建一个日志记录器。要启用日志记录,我们需要在应用程序属性中使用客户端的软件包名称声明日志记录。

logging:  level:    com.pack.feignDEBUG

这将该包中所有客户端的日志记录。如果我们只需要为特定客户端启用日志记录,可以通过在属性中明确指定客户端来实现。

logging:  level:    com.pack.feign.AccountFeignClient: DEBUG

Feign 提供了日志记录级别,以显示我们需要的客户端日志记录级别。让我们在配置类中添加一些基本日志。

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

有4个等级:
NONE:无日志。
BASIC:记录请求方法和 URL 以及响应状态代码和执行时间。
HEADERS:除基本日志记录外,它还记录请求和响应标头。
FULL:记录请求和响应的标头、正文和元数据完整信息。

有关更多关于OpenFeign高级用法,请查看下面这篇文章

OpenFeign高级用法:这些强大的功能你用过吗?


以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

新功能来了!Spring非常实用的5个功能

弃用Spring Cache!首选多级缓存框架JetCache

神器!API接口限流就是这么简单

我给Spring提交一个Bug,已在最新版修复!请这样修复!

手写!Controller接口性能监控

SpringBoot3优雅停止/重启定时任务

SpringBoot3必须掌握的5个强大功能,其中JVM优化技巧太厉害了

SpringBoot中Controller接口参数这样处理太优雅了

请一定掌握SpringBoot这4个高级开发技巧

SpringBoot多租户3种架构实现方案详解

生产环境Spring Boot切记要关闭这个开关

你的项目中是否运用了@ResponseStatus注解?你真的会用?

【强烈推荐】基于内存和Redis的两级 Java 缓存框架

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读38
粉丝0
内容832