【Spring Cloud】Feign最佳实践




前言

  • 本次示例代码的文件结构如下图所示。
    在这里插入图片描述

  • 本文总结了 2 种 Feign 的最佳实践方案。

  • 方式一 (继承) :给消费者的 FeignClient 和提供者的 controller 定义统一的父接口作为标准。

  • 方式二 (抽取) :将 FeignClient 抽取为独立模块,并且把接口有关的 POJO 、默认的 Feign 配置都放在这个模块中,提供给消费者使用。


方式一:继承

  • 本例中,服务的消费者就是订单服务 order-service 。打开其 clients/UserClient.java

    image-20230213133527304


方式二:抽取

  • 以前,消费者远程调用提供者的接口时,都把 FeignClient 写在消费者的服务之中,如下图所示。

    image-20230213134104095

  • 但是,这种写法有个问题。当未来微服务越来越多,大家都来调用 user-service 的接口,那么 UserClient 就写了很多遍,重复开发。

  • 现在,抽取出一个独立的模块 feign-api ,把接口有关的 POJO 、默认的 Feign 配置都放在这个模块中,提供给消费者使用。结构如下所示。

    image-20230213134412695

  • 但是这种方式也有一个缺点,就是当消费者 order-service 只想调用 feign-api 里的一两个方法,而把项目 jar 包整个引入就显得有点冗余了。

  • 可见,两种最佳实践都并不是完美的。如果你在意面向契约编程,就采用方式一。如果你更在意耦合度,那就采用方式二。都要根据具体业务的实际情况决定。


1)创建模块

  • 首先创建一个 module ,命名为 feign-api ,然后引入 feign 的 starter 依赖。

    image-20230213135448984

  • 打开 pom.xml 文件,添加 Feign 的依赖。

    <!-- Feign远程调用客户端 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    

2)迁移到feign-api

  • order-service 中的 UserClientUserDefaultFeignConfiguration 都复制到 feign-api 项目中。

  • 迁移前的 order-service 如下。

    image-20230213140238364

  • 迁移后的 feign-api 如下。

    image-20230213140326665

  • order-service 迁移过去的文件就都可以删除了。


3)在消费者中引入feign-api依赖

  • order-service 中要引入 feign-api 依赖。打开 order-servicepom.xml

    <!-- 引入自己写的feign的统一API -->
    <dependency>
        <groupId>cn.itcast.demo</groupId>
        <artifactId>feign-api</artifactId>
        <version>1.0</version>
    </dependency>
    

4)修改import

  • 修改 order-service 中的所有与上述三个组件有关的 import 部分,改成导入 feign-api 中的包。

    image-20230213140837493

  • OrderService

    image-20230213140939359


5)报错:UserFeign无法注入

  • 启动 OrderApplication 时,发生了如下报错。

    Description:
    
    Field userClient in cn.itcast.order.service.OrderService required a bean of type 'cn.itcast.feign.clients.UserClient' that could not be found.
    
    Action:
    
    Consider defining a bean of type 'cn.itcast.feign.clients.UserClient' in your configuration.
    
  • 这个报错,说明 UserClient 无法注入成功,证明 UserClient 没有创建对象,所以 Spring 在容器中找不到它,从而注入失败。

  • 之前可以成功运行,是因为 UserClientorder-service 项目下,启动类OrderApplication.java 扫描到 UserClient 中的注解 @FeignClient("userservice") ,就可以创建 UserClient 对象。

  • 但是,Spring 中 order-service 项目默认扫描包的范围是其启动类所在的包,本例中只扫描 cn.itcast.order 包。

    image-20230213144801770

  • 而现在 UserClient 所在的包是 cn.itcast.feign 。两者所在的包不一样,因此 order-service 扫描不到。因此 Spring 无法为 UserClient 创建对象。

    image-20230213145001141

  • 当定义的 FeignClient 不在 SpringBootApplication 的扫描包范围时,这些 FeignClient 无法使用。这里有两种方式解决。

  • 【解决方法一】在 OrderApplication.java 的注解 @EnableFeignClients 中指定 FeignClient 所在的包。

    @EnableFeignClients(basePackages = "cn.itcast.feign.clients")
    
  • 【(推荐) 解决方法二】在 OrderApplication.java 的注解 @EnableFeignClients 中指定 FeignClient 字节码,多个用逗号分隔。

    @EnableFeignClients(clients = {
          
          UserClient.class})
    

猜你喜欢

转载自blog.csdn.net/Sihang_Xie/article/details/129009892