zoukankan      html  css  js  c++  java
  • Spring cloud多模块开发下Feign的使用,以及@FeignClient注入bean找不到异常解决

    原文:https://blog.csdn.net/github_39577257/article/details/81842234

    一、关于Feign
    在微服务架构开发是,我们常常会在一个项目中调用其他服务,其实使用Spring Cloud Rbbon就能实现这个需求,利用RestTemplate 的请求拦截来实现对依赖服务的接口调用, 但是实际项目中对服务依赖的调用可能不止于 一 处,往往 一 个接口会被多处调用,所以我们通常都会针对各个微服务自行封装 一 些客户端类来包装这些依赖服务的调用。 这个时候我们会发现,由于 RestTemplate 的封装,几乎每 一 个调用都是简单的模板化内容。

    Spring Cloud Feign 在此基础上做了进 一 步封装,由它来帮助我们定义和实现依赖服务接口的定义。在 Spring Cloud Feign 的实现下, 我们只需创建 一 个接口并用注解(@FeignClient)的方式来配置它, 即可完成对服务提供方的接口绑定,简化了在使用 Spring Cloud Ribbon 时自行封装服务调用客户端的开发量。 

    二、多模块方式构建一个Feign项目
    1、准备,

    启动一个Eureka服务注册中心,后面的两个服务都会启动注册到这个上面。

    2、编写第一服务--商品服务

    (1). 创建一个父模块

      File-->New-->Project-->Maven

      不需要任何勾选,直接填写GAV,然后填写项目名就可以了

      因为这是一个父模块,对于创建出来的Maven项目,可以直接删除src文件

    (2). 创建子模块common

      在父模块上右键`New`-->`Module`,创建一个模块,该模块即为子模块;

      同样不选择Create from archetype选项,因为是普通模块,Next;

      GroupId       默认父项目的groupId

      Version       默认父项目的version

      ArtifactId    本模块的名字product-common

      然后填写项目名即可common

    (3). 同理创建子模块client

      在父模块上右键`New`-->`Module`,创建一个子模块;

      同样不选择Create from archetype选项,因为是普通模块,Next;

      GroupId       默认父项目的groupId

      Version       默认父项目的version

      ArtifactId    本模块的名字product-client

      然后填写项目名即可client

    (4). 同理创建子模块server

      在父模块上右键`New`-->`Module`,创建一个子模块;

      同样不选择Create from archetype选项,因为是普通模块,Next;

      GroupId       默认父项目的groupId

      Version       默认父项目的version

      ArtifactId    本模块的名字product-server

      然后填写项目名即可server

    (5). 在server模块下编写一个服务接口

      例如提供一个/product/ listForOrder,这个服务会在下面的订单类中调用

    @RestController
    @RequestMapping("/product")
    public class ProductController {
    @Autowired
    private ProductService productService;

    @PostMapping("/listForOrder")
    public List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList){

        return productService.findList(productIdList);

    }
    }
    (6). 在client模块下创建一个接口类

    在这个接口类上加注解@FeignClient(name = "product"),其中product是配置的服务在注册中心上的名字

    import com.yore.product.common.ProductInfoOutput;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;

    import java.util.List;

    @FeignClient(name = "product")
    public interface ProductClient {

        @PostMapping("/product/listForOrder")

        List<ProductInfoOutput> listForOrder(@RequestBody List<String> productIdList);

    }
    (7). 接此项目提交到Maven仓库

    直接可以使用Idea右侧的Maven Projects里的install,打包提交到Maven仓库,或者使用Maven命令:

    mvn -Dmaven.test.skip=true -U clean install
    (8). 启动项目,将项目注册到注册中心,


    启动成功后会在注册中心的UI上看到服务的注册信息

    3、编写第二服务—订单服务

    (1). 同第2.2创建商品项目一样,创建一个订单Maven项目

    (2). 在项目中把商品类的client依赖引入项目

    (3). 在订单项目的Server模块的应用启动类上添加注解

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients(basePackages = "com.yore.product.client")
    public class OrderApplication {

        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class,args);
        }

    }
    (4). 在Server模块调用商品服务

    这里比如在服务层调用,只需要在该类把订单类提供的ProductClient接口自动注解进来,就可以使用商品类向外提供的接口服务

    三、项目引入的依赖
    Spring Cloud确实开发更加方便了,Spring Cloud版本更新也很快,但是头疼的就是个个版本的兼容性就是很不方便的地方,经常因为版本问题会调入坑里不能自拔,所以如果有时排查后确定不是项目代码问题时,实在没有办法时还是降版本吧。

    1、商品类引用的依赖

    父pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yore</groupId>
    <artifactId>product</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <modules>
    <module>common</module>
    <module>client</module>
    <module>server</module>
    </modules>
    <packaging>pom</packaging>

    <name>product</name>

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.RELEASE</version>
    <relativePath/>
    </parent>

    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Finchley.M9</spring-cloud.version>
    <product-common.version>0.0.1-SNAPSHOT</product-common.version>
    </properties>

    <!-- 依赖的版本管理 -->
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <!-- 项目中引用common -->
    <dependency>
    <groupId>com.yore</groupId>
    <artifactId>product-common</artifactId>
    <version>${product-common.version}</version>
    </dependency>
    </dependencies>
    </dependencyManagement>

    </project>
    client模块Pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>product</artifactId>
    <groupId>com.yore</groupId>
    <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>product-client</artifactId>

    <dependencies>
    <!-- 项目中用到了Feign注解,引入此包 -->
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <!-- 项目中用到了PostMapping,引入此包 -->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    </dependency>

    </dependencies>

    </project>
    service模块Pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>product</artifactId>
    <groupId>com.yore</groupId>
    <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>product-server</artifactId>

    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>

    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>

    </project>
     

    2、订单类引用的依赖

    父Pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yore</groupId>
    <artifactId>order</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <modules>
    <module>client</module>
    <module>common</module>
    <module>server</module>
    </modules>
    <packaging>pom</packaging>

    <name>order</name>

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.4.RELEASE</version>
    <relativePath/>
    </parent>

    <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Finchley.M9</spring-cloud.version>
    <product-client.version>0.0.1-SNAPSHOT</product-client.version>
    </properties>

    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
    </dependency>
    <dependency>
    <groupId>com.yore</groupId>
    <artifactId>product-client</artifactId>
    <version>${product-client.version}</version>
    </dependency>
    </dependencies>
    </dependencyManagement>

    <repositories>
    <repository>
    <id>spring-snapshots</id>
    <name>Spring Snapshots</name>
    <url>https://repo.spring.io/snapshot</url>
    <snapshots>
    <enabled>true</enabled>
    </snapshots>
    </repository>
    <repository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
    <snapshots>
    <enabled>false</enabled>
    </snapshots>
    </repository>
    </repositories>

    <pluginRepositories>
    <pluginRepository>
    <id>spring-snapshots</id>
    <name>Spring Snapshots</name>
    <url>https://repo.spring.io/snapshot</url>
    <snapshots>
    <enabled>true</enabled>
    </snapshots>
    </pluginRepository>
    <pluginRepository>
    <id>spring-milestones</id>
    <name>Spring Milestones</name>
    <url>https://repo.spring.io/milestone</url>
    <snapshots>
    <enabled>false</enabled>
    </snapshots>
    </pluginRepository>
    </pluginRepositories>


    </project>
    server模块Pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>order</artifactId>
    <groupId>com.yore</groupId>
    <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order-server</artifactId>

    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-context</artifactId>
    </dependency>

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>


    <dependency>
    <groupId>com.yore</groupId>
    <artifactId>product-client</artifactId>
    </dependency>

    <dependency>
    <groupId>com.yore</groupId>
    <artifactId>order-common</artifactId>
    </dependency>

    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>

    </project>
     

    四、问题
    1、LoadBalancedRetryFactory类无法加载的异常

    java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration] from ClassLoader

    Caused by: java.lang.NoClassDefFoundError: org/springframework/cloud/client/loadbalancer/LoadBalancedRetryFactory
    这个是某些Spring Cloud非正式版本会出现的问题,有些人使用是可能不会出现这个问题,有时人品不好时就会包这个问题,出现这个问题就不要瞎折腾了,直接更换成正式版的吧,可以参考上面引入的版本,Reimport一下

    2、提供的某些Fegin服务无法找到

    Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
    2018-08-19 21:28:20.526 ERROR 20068 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :

    ***************************
    APPLICATION FAILED TO START
    ***************************

    Description:

    Field productClient in com.yore.order.service.impl.OrderServiceImpl required a bean of type 'com.yore.product.client.ProductClient' that could not be found.


    Action:

    Consider defining a bean of type 'com.yore.product.client.ProductClient' in your configuration.
    出现这个问题,首先要确定在启动类上是否添加了@EnableFeignClients注解,并且需要配置上Feign客户端接口的包basePackages = "com.yore.product.client",

    @EnableFeignClients(basePackages = "com.yore.product.client")
    然后确定这两个服务引用的Spring Cloud和Spring Boot版本是否一致,有时因为不一致,在 第一个服务中注解可能引用的是org.springframework.cloud.netflix.feign.FeignClient这个包下的,另一个服务中引用的是org.springframework.cloud.openfeign.FeignClient包下的,这时也会包这个错误,

     
    ————————————————
    版权声明:本文为CSDN博主「YoreYuan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/github_39577257/article/details/81842234

  • 相关阅读:
    游戏开发挑战中心规划(16)
    游戏开发关卡设计(16)
    借鉴来的面试经验
    Scrapy:学习笔记(2)——Scrapy项目
    Scrapy:学习笔记(1)——XPath
    Django:学习笔记(8)——文件上传
    And Design:拓荒笔记——Form表单
    React:快速上手(7)——使用中间件实现异步操作
    JavaScript:学习笔记(9)——Promise对象
    JavaScript:学习笔记(8)——对象扩展运算符
  • 原文地址:https://www.cnblogs.com/dayspring/p/14587958.html
Copyright © 2011-2022 走看看