SpringCloud之OpenFeign调用解读

简介: SpringCloud之OpenFeign调用解读

基本介绍

引进

如果我们利用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代码实战

实战架构

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

父工程pom文件

统一管理版本信息

    <groupId>org.example</groupId>
    <artifactId>eurek-test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>eurek-serve</module>
        <module>student-service</module>
        <module>teacher-service</module>
    </modules>
    <packaging>pom</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.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>Hoxton.SR10</spring-cloud.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>2.1.1</mybatis.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- springCloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--nacos的管理依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

teacher-service服务

pom文件

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <!-- nacos客户端依赖包 -->
       <dependency>
           <groupId>com.alibaba.cloud</groupId>
           <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
       </dependency>
   </dependencies>

启动类

@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文件

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <!-- nacos客户端依赖包 -->
       <dependency>
           <groupId>com.alibaba.cloud</groupId>
           <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-openfeign</artifactId>
       </dependency>
   </dependencies>

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即可。


相关文章
|
2月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
56 0
|
2月前
|
消息中间件 Cloud Native Java
【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合
【Spring云原生系列】SpringBoot+Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合
|
2月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
171 0
|
2月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
108 0
|
2月前
|
消息中间件 JSON Java
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
Spring Boot、Spring Cloud与Spring Cloud Alibaba版本对应关系
776 0
|
8天前
|
负载均衡 前端开发 Java
第六章 Spring Cloud 之 OpenFeign
第六章 Spring Cloud 之 OpenFeign
10 0
|
8天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
1月前
|
开发框架 负载均衡 Java
Spring boot与Spring cloud之间的关系
总之,Spring Boot和Spring Cloud之间的关系是一种构建和扩展的关系,Spring Boot提供了基础,而Spring Cloud在此基础上提供了分布式系统和微服务架构所需的扩展和工具。
19 4
Spring boot与Spring cloud之间的关系
|
2月前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
68 1
|
2月前
|
Java Nacos Sentinel
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(九)Nacos+Sentinel+Seata
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(九)Nacos+Sentinel+Seata
215 0