您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

SpringBoot 使用 Feign 无废话 All-in-one 指南

时间:2022-11-27 16:58:51  来源:稀土掘金  作者:程序猿不相信眼泪

开篇

Feign 是声明式、模板化的 HTTP 客户端, 可以帮助我们更快捷、优雅地调用 HTTP API;Spring Cloud 为 Feign 添加了 Spring MVC 的注解支持,并整合了 Ribbon 和 Eureka 来为使用 Feign 时提供负载均衡;在 Spring Cloud 中使用 Feign 是非常容易的。

本篇主要介绍 SpringBoot 中要玩转 Feign 需要掌握的如添加 pom 依赖、客户端注解启用、切换底层 HttpClient、配置数据压缩、调整日志级别、定制配置、配置的优先级机制、增加拦截器以及拦截器的追加机制等知识。

一、使用 Feign 的示例

1.1 添加依赖

<dependencies>
  <!--openfein的依赖-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
      <version>2.1.3.RELEASE</version>
  </dependency>
</dependencies>
复制代码

1.2 启用 Feign

在 SpringBoot 的启用类上添加注解@EnableFeignClients,@EnableFeignClients用于开启 Feign,会自动扫描@FeignClient标注的 FeignClient 接口。

@SpringBootApplication
@EnableFeignClients
@EnableWeb
public class FeignApplication {
    public static void mAIn(String[] args) {
        SpringApplication.run(FeignApplication.class,args);
    }
}
复制代码

1.3 编写 FeignClient 接口

@FeignClient(
        name = "demo-service",
        url = "http://localhost:8080/feign/server/",
        configuration = FeignInterceptor.class,
        fallback = TestService.DefaultFallback.class
)
public interface TestService {

    @RequestMapping(value = "/getError/{id}", method = RequestMethod.GET)
    public String getError(@RequestParam("id") Integer id);


    @RequestMapping(value = "/get1", method = RequestMethod.GET)
    public String get1();

    @RequestMapping(value = "/get2/{param}", method = RequestMethod.GET)
    public String get2(@RequestParam("param") String param);

    @RequestMapping(value = "/post1", method = RequestMethod.POST)
    public FeignDemo post1(@RequestBody FeignDemo demo);
复制代码

1.4 编写对应的服务端

@RestController
@RequestMapping("/feign/server")
public class FeignServerController {

    @GetMapping("/get1")
    public String get1() {
        return "get1";
    }
    @GetMapping("/get2/{para}")
    public String get2(@PathVariable("para") String para){
        return para;
    }
    @PostMapping("/post1")
    public FeignDemo  post1(@RequestBody FeignDemo demo) {
        return demo;
    }
}
复制代码
public class FeignDemo {
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "FeignDemo{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}
复制代码

1.5 调用 FeignClient

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {FeignApplication.class},webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ActiveProfiles("dev,feign")
public class FeignClientTest {

    @Autowired
    private TestService testService;

    @Test
    public void testFallback(){
        testService.getError(1);
    }
    @Test
    public void testGet1(){
        System.out.println(testService.get1());
        System.out.println(testService.get2("abc"));
        System.out.printf("..");
        FeignDemo feignDemo = new FeignDemo();
        feignDemo.setName("name");
        feignDemo.setAge(1);
        System.out.println(testService.post1(feignDemo));
    }

@Component
    public class DefaultFallback implements TestService {

        @Override
        public String getError(@RequestParam("id") Integer id){
            return "";
        }

        @Override
        public String get1() {
            return null;
        }

        @Override
        public String get2(String param) {
            return null;
        }

        @Override
        public FeignDemo post1(FeignDemo demo) {
            return null;
        }

    }
}
复制代码

二、如何切换 Client

Feign 中自带的是 HttpURLConnection,这个 client 健壮性差,可替换为成熟的 Apache HttpClient 或 OkHttp 来进行网络请求。

2.1 使用 Apache 的 HTTP Client

使用 Apache 的 httpclient 替换 Feign 中默认的 client。

2.1.1 添加依赖

<!--httpclient的依赖,因为选择了使用httpclient-->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>
<dependency>
    <groupId>io.Github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
    <version>10.4.0</version>
</dependency>
复制代码

2.1.2 配置启用

配置中添加如下信息,表示启用httpclient。

feign:
  httpclient:
    enabled: true
复制代码

2.2 使用 OkHttp

2.2.1 添加依赖

在 Feign 中使用OkHttp作为网络请求框架,则只需要在 pom 文件中加上feign-okhttp的依赖,代码如下:

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
    <version>10.2.0</version>
</dependency>
复制代码

2.2.2 配置启用

feign:
  okhttp:
    enabled: true
复制代码

三、如何修改日志级别

在发送和接收请求的时候,其内部将日志的打印输出定义成了四个等级,对应的详情如下:

级别

说明

NONE

不做任何记录

BASIC

仅记录请求方法和 URL 以及响应状态代码和执行时间

HEADERS

记录基本信息以及请求和响应标头

FULL

记录请求和响应的标题,正文和元数据

3.1 通过配置文件修改日志级别

注意需要指定接口的全限定名

logging:
  level:
    com.zto.titans.test.feign.service.TestService : DEBUG
复制代码

3.2 通过配置类修改日志级别

@Configuration
public class FooConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
复制代码

这个一看即懂,不再废话。

四、如何实现数据压缩

可以分别对 HTTP 通信的request和response设置是否启用 GZIP 压缩,配置方法如下:

feign:
    compression:
        request:
            enabled: true
            mime-types: text/xml,application/xml,application/json # 配置压缩支持的MIME TYPE
            min-request-size: 2048  # 配置压缩数据大小的下限
        response:
            enabled: true # 配置响应GZIP压缩
复制代码

五、FeignClient 的配置以及配置的优先级机制

有 2 种途径设置 FeignClient 的配置,通过自定义配置类来设置配置和在配置文件中设置,其中配置文件方式有点特殊,它里边可以指定全局配置对所有 FeignClient 有效,也可以为特定名称的 FeignClient 设置专属的配置。

5.1 通过自定义配置类来定制配置

实现一个配置类

public class TestConfiguration {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
复制代码

将配置类 TestConfiguration 指定给configuration。

@FeignClient(
        name = "test-service",
        configuration = {FeignInterceptor2.class,TestConfiguration.class}
)
复制代码

5.2 在配置文件中设置全局配置

feign.client.config.default.xxx ,这个default意为全局的配置属性。

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic
复制代码

5.3 在配置文件中设置专属配置

feign.client.config.feignName.xxx , 给名字为feignName的FeignClient指定专属的配置。

feign:
  client:
    config:
      feignName:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: full
        errorDecoder: com.example.SimpleErrorDecoder
        retryer: com.example.SimpleRetryer
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false
        encoder: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
复制代码

5.4 理解配置的优先级与拦截器的追加原则


org.springframework.cloud.openfeign.FeignClientFactoryBean#configureFeign中可以确认以上 3 种配置的优先级:

configureUsingConfiguration(context, builder); // 1
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()),builder); //2
configureUsingProperties(properties.getConfig().get(this.contextId),builder);//3
复制代码
  1. 第 1 类为通过自定义配置类来指定配置
  2. 第 2 类为在配置文件中的feign.client.config.default.xxx设置全局配置
  3. 第 3 类为在配置文件中的feign.client.config.feignName.xxx设置专属配置

5.4.1 优先级的效果

配置文件里的专属配置 -覆盖-> 配置文件里的全局配置 -覆盖-> 配置类的配置

5.4.2 追加的原则

RequestInterceptor 是拦截器,可以在发送前做一些处理,比如统一添加header信息。每一类中的requestInterceptors可以存储多个拦截器,拦截器并非覆盖的效果,而是链式追加的效果;从执行顺序来看优先级是:1 > 2 > 3,即先执行 配置类中指定的拦截器,然后是 配置文件中指定的全局拦截器,最后是配置文件中指定的专属拦截器

需特别注意:RequestInterceptor 的实现类(例如 RI-A,RI-B)上如果添加了@Component注解,就都会被扫描识别到,并被追加到第一类的requestInterceptors列表中;倘若不小心 RI-A 还在第 2 类中又被指定了,则还会将拦截器 RI-A 追加在第二类的requestInterceptors列表中,结果是会 RI-A 总计会执行 2 次;若也在第三类中指定 RI-A,则 RI-A 也在其列表中追加,结果是 RI-A 总计会执行 3 次。

5.4.3 拦截器的效果验证

以一个实例来验证说明效果

  • 自定义三个 RequestInterceptor
class FeignInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("user", "myuser1");
        requestTemplate.header("password", "mypassword");
    }
}
复制代码
class FeignInterceptor1 implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("user1", "myuser1");
        requestTemplate.header("password1", "mypassword1");
    }
}
复制代码
class FeignInterceptor2 implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("user2", "myuser2");
        requestTemplate.header("password2", "mypassword2");
    }
}
复制代码
  • @FeignClient 中指定一个
@FeignClient(
        name = "test-service",
        url = "http://localhost:8080/feign/server/",
        configuration = {FeignInterceptor.class,TestConfiguration.class},
        fallback = TestService.DefaultFallback.class
)
复制代码
  • 配置中指定 2 个

default 指定了一个,test-service里指定一个

feign:
  httpclient:
    enabled: true
  okhttp:
    enabled: true
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        #loggerLevel: none
        requestInterceptors:
          - com.zto.titans.test.feign.service.FeignInterceptor1
      test-service:
        #loggerLevel: basic
        requestInterceptors:
          - com.zto.titans.test.feign.service.FeignInterceptor2
logging:
  level:
    com.zto.titans.test.feign.service.TestService : DEBUG
复制代码

根据追加逻辑,最终执行的顺序是:

  1. FeignInterceptor
  2. FeignInterceptor1
  3. FeignInterceptor2

总结

本篇主要介绍 SpringBoot 中要玩转 Feign 需要掌握的如添加 pom 依赖、客户端注解启用、切换底层 HttpClient、配置数据压缩、调整日志级别、定制配置、配置的优先级机制、增加拦截器以及拦截器的追加机制等知识,以实例 + 效果的方式帮读者高效全面并深入的理解它们。


原文链接:
https://juejin.cn/post/7169549885723639838
来源:稀土掘金



Tags:SpringBoot   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  Search: SpringBoot  点击:(19)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19  Search: SpringBoot  点击:(86)  评论:(0)  加入收藏
SpringBoot3+Vue3 开发高并发秒杀抢购系统
开发高并发秒杀抢购系统:使用SpringBoot3+Vue3的实践之旅随着互联网技术的发展,电商行业对秒杀抢购系统的需求越来越高。为了满足这种高并发、高流量的场景,我们决定使用Spring...【详细内容】
2024-01-14  Search: SpringBoot  点击:(91)  评论:(0)  加入收藏
公司用了六年的 SpringBoot 项目部署方案,稳得一批!
本篇和大家分享的是springboot打包并结合shell脚本命令部署,重点在分享一个shell程序启动工具,希望能便利工作。 profiles指定不同环境的配置 maven-assembly-plugin打发布压...【详细内容】
2024-01-10  Search: SpringBoot  点击:(166)  评论:(0)  加入收藏
简易版的SpringBoot是如何实现的!!!
SpringBoot作为目前最流行的框架之一,同时是每个程序员必须掌握的知识,其提供了丰富的功能模块和开箱即用的特性,极大地提高了开发效率和降低了学习成本,使得开发人员能够更专注...【详细内容】
2023-12-29  Search: SpringBoot  点击:(136)  评论:(0)  加入收藏
用 SpringBoot+Redis 解决海量重复提交问题
前言 一:搭建redis的服务Api 二:自定义注解AutoIdempotent 三:token创建和检验 四:拦截器的配置 五:测试用例 六:总结前言:在实际的开发项目中,一个对外暴露的接口往往会面临很多...【详细内容】
2023-12-20  Search: SpringBoot  点击:(53)  评论:(0)  加入收藏
SpringBoot中如何优雅地个性化定制Jackson
当使用 JSON 格式时,Spring Boot 将使用ObjectMapper实例来序列化响应和反序列化请求。在本教程中,我们将了解配置序列化和反序列化选项的最常用方法。一、默认配置默认情况下...【详细内容】
2023-12-20  Search: SpringBoot  点击:(132)  评论:(0)  加入收藏
springboot-如何集成Validation进行参数校验
一、步骤概览 二、步骤说明1.引入依赖包在 pom.xml 文件中引入 validation 组件,它提供了在 Spring Boot 应用程序中进行参数校验的支持。<!-- WEB 程序依赖包 --><dependen...【详细内容】
2023-12-13  Search: SpringBoot  点击:(157)  评论:(0)  加入收藏
优雅的springboot参数校验,你学会了吗?
前言在后端的接口开发过程,实际上每一个接口都或多或少有不同规则的参数校验,有一些是基础校验,如非空校验、长度校验、大小校验、格式校验;也有一些校验是业务校验,如学号不能重...【详细内容】
2023-11-29  Search: SpringBoot  点击:(200)  评论:(0)  加入收藏
Springboot扩展点之BeanDefinitionRegistryPostProcessor,你学会了吗?
前言通过这篇文章来大家分享一下,另外一个Springboot的扩展点BeanDefinitionRegistryPostProcessor,一般称这类扩展点为容器级后置处理器,另外一类是Bean级的后置处理器;容器级...【详细内容】
2023-11-27  Search: SpringBoot  点击:(175)  评论:(0)  加入收藏
▌简易百科推荐
Qt与Flutter:在跨平台UI框架中哪个更受欢迎?
在跨平台UI框架领域,Qt和Flutter是两个备受瞩目的选择。它们各自具有独特的优势,也各自有着广泛的应用场景。本文将对Qt和Flutter进行详细的比较,以探讨在跨平台UI框架中哪个更...【详细内容】
2024-04-12  刘长伟    Tags:UI框架   点击:(1)  评论:(0)  加入收藏
Web Components实践:如何搭建一个框架无关的AI组件库
一、让人又爱又恨的Web ComponentsWeb Components是一种用于构建可重用的Web元素的技术。它允许开发者创建自定义的HTML元素,这些元素可以在不同的Web应用程序中重复使用,并且...【详细内容】
2024-04-03  京东云开发者    Tags:Web Components   点击:(8)  评论:(0)  加入收藏
Kubernetes 集群 CPU 使用率只有 13% :这下大家该知道如何省钱了
作者 | THE STACK译者 | 刘雅梦策划 | Tina根据 CAST AI 对 4000 个 Kubernetes 集群的分析,Kubernetes 集群通常只使用 13% 的 CPU 和平均 20% 的内存,这表明存在严重的过度...【详细内容】
2024-03-08  InfoQ    Tags:Kubernetes   点击:(19)  评论:(0)  加入收藏
Spring Security:保障应用安全的利器
SpringSecurity作为一个功能强大的安全框架,为Java应用程序提供了全面的安全保障,包括认证、授权、防护和集成等方面。本文将介绍SpringSecurity在这些方面的特性和优势,以及它...【详细内容】
2024-02-27  风舞凋零叶    Tags:Spring Security   点击:(55)  评论:(0)  加入收藏
五大跨平台桌面应用开发框架:Electron、Tauri、Flutter等
一、什么是跨平台桌面应用开发框架跨平台桌面应用开发框架是一种工具或框架,它允许开发者使用一种统一的代码库或语言来创建能够在多个操作系统上运行的桌面应用程序。传统上...【详细内容】
2024-02-26  贝格前端工场    Tags:框架   点击:(47)  评论:(0)  加入收藏
Spring Security权限控制框架使用指南
在常用的后台管理系统中,通常都会有访问权限控制的需求,用于限制不同人员对于接口的访问能力,如果用户不具备指定的权限,则不能访问某些接口。本文将用 waynboot-mall 项目举例...【详细内容】
2024-02-19  程序员wayn  微信公众号  Tags:Spring   点击:(39)  评论:(0)  加入收藏
开发者的Kubernetes懒人指南
你可以将本文作为开发者快速了解 Kubernetes 的指南。从基础知识到更高级的主题,如 Helm Chart,以及所有这些如何影响你作为开发者。译自Kubernetes for Lazy Developers。作...【详细内容】
2024-02-01  云云众生s  微信公众号  Tags:Kubernetes   点击:(51)  评论:(0)  加入收藏
链世界:一种简单而有效的人类行为Agent模型强化学习框架
强化学习是一种机器学习的方法,它通过让智能体(Agent)与环境交互,从而学习如何选择最优的行动来最大化累积的奖励。强化学习在许多领域都有广泛的应用,例如游戏、机器人、自动驾...【详细内容】
2024-01-30  大噬元兽  微信公众号  Tags:框架   点击:(68)  评论:(0)  加入收藏
Spring实现Kafka重试Topic,真的太香了
概述Kafka的强大功能之一是每个分区都有一个Consumer的偏移值。该偏移值是消费者将读取的下一条消息的值。可以自动或手动增加该值。如果我们由于错误而无法处理消息并想重...【详细内容】
2024-01-26  HELLO程序员  微信公众号  Tags:Spring   点击:(88)  评论:(0)  加入收藏
SpringBoot如何实现缓存预热?
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到缓存系...【详细内容】
2024-01-19   Java中文社群  微信公众号  Tags:SpringBoot   点击:(86)  评论:(0)  加入收藏
站内最新
站内热门
站内头条