SpringCloud之OpenFeign调用解读
作者:mmseoamin日期:2023-12-20

目录

基本介绍

引进

OpenFeign概述

OpenFeign作用 

@FeignClient 

@EnableFeignClients 

Java代码实战

实战架构

父工程pom文件 

teacher-service服务

student-service服务

测试

自定义配置


基本介绍

引进

如果我们利用RestTemplate发起远程调用的代码时会存在一些问题比如:

•代码可读性差,编程体验不统一

•参数复杂URL难以维护

String url="http://teacherservice/getTeacher";
Teacher teacher = restTemplate.getForObject(url, Teacher.class);

OpenFeign概述

OpenFeign是一个显示声明式的WebService客户端。使用OpenFeign能让编写Web Service客户端更加简单。使用时只需定义服务接口,然后在上面添加注解。OpenFeign也支持可拔插式的编码和解码器。spring cloud对feign进行了封装,使其支持MVC注解和HttpMessageConverts。和eureka(服务注册中心)和ribbon组合可以实现负载均衡。

在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求,非常的方便。

cloud官网介绍Feign:Spring Cloud OpenFeign

OpenFeign源码:GitHub - OpenFeign/feign: Feign makes writing java http clients easier

OpenFeign作用 

  • OpenFeign的设计宗旨式简化Java Http客户端的开发。Feign在restTemplate的基础上做了进一步的封装,由其来帮助我们定义和实现依赖服务接口的定义。在OpenFeign的协助下,我们只需创建一个接口并使用注解的方式进行配置(类似于Dao接口上面的Mapper注解)即可完成对服务提供方的接口绑定,大大简化了Spring cloud Ribbon的开发,自动封装服务调用客户端的开发量。
  • OpenFeign集成了Ribbon,利用ribbon维护了服务列表,并且通过ribbon实现了客户端的负载均衡。与ribbon不同的是,通过OpenFeign只需要定义服务绑定接口且以申明式的方法,优雅而简单的实现了服务调用。

    @FeignClient 

    @FeignClient 实现的是声明式的、模块化的Http客户端,可以让我们对其他服务接口的访问更边界就像是controller和service之间的调用一样。

    @FeignClient属性如下:

    • name:指定该类的容器名称,类似于@Service(容器名称)
    • url: url一般用于调试,可以手动指定@FeignClient调用的地址
    • decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
    •  configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
    •  fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
    • fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
    • path: 定义当前FeignClient的统一前缀,当我们项目中配置了server.context-path,server.servlet-path时使用
      @FeignClient(name="teacherservice")
      public interface TeacherServiceFeign {
          @GetMapping("/getTeacher/{id}")
          Teacher getInfo(@PathVariable("id") String id);
      }

      @EnableFeignClients 

      在的启动类添加​ @EnableFeignClients注解开启Feign的功能  

      用注解@EnableFeignClients启用feign客户端;扫描和注册feign客户端bean定义

      @EnableFeignClients注解中的basePackges属性中是一个数组,可以填写多个值,其主要作用是指定当前模块中需要用到那些地址下的feign接口,起到一个discovery发现feign接口的作用。

      Java代码实战

      实战架构

      SpringCloud之OpenFeign调用解读,第1张

      俩个为俩个不同的端口的service端,客户端向8002端口的studentservice发送一个请求(/getInfo/{id})以后,8002端口的studentservice需要往teacherservice发送一个请求(/getTeacher/{id})返回数据。

      父工程pom文件 

      统一管理版本信息 

          org.example
          eurek-test
          1.0-SNAPSHOT
          
              eurek-serve
              student-service
              teacher-service
          
          pom
          
              org.springframework.boot
              spring-boot-starter-parent
              2.3.12.RELEASE
              
          
          
              UTF-8
              UTF-8
              1.8
              Hoxton.SR10
              5.1.47
              2.1.1
          
          
              
                  
                  
                      org.springframework.cloud
                      spring-cloud-dependencies
                      ${spring-cloud.version}
                      pom
                      import
                  
                  
                  
                      com.alibaba.cloud
                      spring-cloud-alibaba-dependencies
                      2.2.5.RELEASE
                      pom
                      import
                  
              
          
          
              
                  org.projectlombok
                  lombok
              
          

      teacher-service服务

       pom文件

         
             
                 org.springframework.boot
                 spring-boot-starter-web
             
             
             
                 com.alibaba.cloud
                 spring-cloud-starter-alibaba-nacos-discovery
             
         

      启动类

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

      yml配置文件 

      server:
        port: 8002
      spring:
        application:
          name: teacherservice
        cloud:
          nacos:
            server-addr: localhost:8848

       Teacher类

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class Teacher implements Serializable {
          private  String name;
          private  String sex;
      }

      TeachertController

      @RestController
      public class TeacherController {
          @GetMapping("/getTeacher/{id}")
          public Teacher getInfo(@PathVariable("id") String id){
              return new Teacher("张三-"+id,"男");
          }
      }

      student-service服务

      pom文件

         
             
                 org.springframework.boot
                 spring-boot-starter-web
             
             
             
                 com.alibaba.cloud
                 spring-cloud-starter-alibaba-nacos-discovery
             
             
                 org.springframework.cloud
                 spring-cloud-starter-openfeign
             
         

      yml配置文件 

      server:
        port: 8002
      spring:
        application:
          name: studentservice
        cloud:
          nacos:
            server-addr: localhost:8848

       启动类 

      @SpringBootApplication
      @EnableFeignClients
      public class StudentApplication {
          public static void main(String[] args) {
              SpringApplication.run(StudentApplication.class,args);
          }
      }

       Teacher类

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class Teacher implements Serializable {
          private  String name;
          private  String sex;
      }

      TeacherServiceFeign ​ 

      @FeignClient("teacherservice")
      public interface TeacherServiceFeign {
          @GetMapping("/getTeacher/{id}")
          Teacher getInfo(@PathVariable("id") String id);
      }

      个客户端主要是基于SpringMVC的注解来声明远程调用的信息,比如:

      • 服务名称:teacherservice

      • 请求方式:GET

      • 请求路径:/getTeacher/{id}

      • 请求参数:String id

      • 返回值类型:Teacher

        这样,Feign就可以帮助我们发送http请求,无需自己使用RestTemplate来发送了。

         StudentController

        @RestController
        public class StudentController implements Serializable {
            @Autowired
            TeacherServiceFeign teacherServiceFeign;
            @GetMapping("/getInfo")
            public Teacher getInfo(){
                Teacher teacher = teacherServiceFeign.getInfo("111");
                return teacher;
            }
        }

        测试

        GET http://localhost:8002/getInfo

        HTTP/1.1 200 

        Content-Type: application/json

        Transfer-Encoding: chunked

        Date: Tue, 17 Oct 2023 02:46:43 GMT

        Keep-Alive: timeout=60

        Connection: keep-alive

        {

          "name": "张三-111",

          "sex": "男"

        }

        自定义配置

        Feign可以支持很多的自定义配置,如下表所示:

        类型作用说明
        feign.Logger.Level修改日志级别包含四种不同的级别:NONE、BASIC、HEADERS、FULL
        feign.codec.Decoder响应结果的解析器http远程调用的结果做解析,例如解析json字符串为java对象
        feign.codec.Encoder请求参数编码将请求参数编码,便于通过http请求发送
        feign. Contract支持的注解格式默认是SpringMVC的注解
        feign. Retryer失败重试机制请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

        一般情况下,默认值就能满足我们使用,如果要自定义时,只需要创建自定义的@Bean覆盖默认Bean即可。