Http 客户端 Feign 学习笔记

news/2025/12/5 22:45:58/文章来源:https://www.cnblogs.com/2678066103hs/p/19313864

从 RestTemplate 到 Feign

RestTemplate 存在的问题

在未使用 Feign 之前,使用 RestTemplate 发起远程调用的代码如下:

String url = "http://userservice/user/" + order.getUserId();
User user = restTemplate.getForObject(url, User.class);

核心痛点:

  • 代码可读性差:URL 拼接丑陋,参数多时难以维护。
  • 编程体验不统一:需要手动处理 HTTP 请求细节,而不是像调用 Java 方法一样简单。
  • 参数复杂 URL 难以维护:特别是当参数包含复杂对象时,GET 请求的 URL 构造非常痛苦。

Feign 介绍

Feign 是一个声明式的 Http 客户端。它的作用是帮助我们优雅地实现 Http 请求的发送。

  • 声明式:只需要定义接口,加上注解,像调用本地方法一样调用远程服务。
  • 集成了 Ribbon:自动实现负载均衡调用。

快速入门使用

使用步骤

第 1 步:引入依赖

在微服务消费端(调用方)引入 openfeign 依赖:

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

第 2 步:开启 Feign 功能

启动类上添加注解 @EnableFeignClients

@EnableFeignClients // 核心注解:扫描 FeignClient 接口并生成动态代理
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}
}

第 3 步:编写 Feign 客户端接口

创建一个接口,使用 SpringMVC 的注解来声明远程调用的信息:

@FeignClient("userservice") // 指定服务名称,Ribbon 会根据这个名称进行负载均衡
public interface UserClient {@GetMapping("/user/{id}") User findById(@PathVariable("id") Long id);
}

关键点解析:

  • 服务名称:userservice
  • 请求方式:GET
  • 请求路径:/user/{id}
  • 请求参数:Long id
  • 返回值:User

第 4 步:在使用处注入并调用

@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate UserClient userClient; // 像注入 Mapper 一样注入 FeignClientpublic Order queryOrderById(Long orderId) {// 1. 查询订单Order order = orderMapper.findById(orderId);// 2. 使用 Feign 远程调用User user = userClient.findById(order.getUserId());// 3. 封装 user 到 Orderorder.setUser(user);// 4. 返回return order;}
}

常见问题

  • 复杂参数处理:如果是对象参数,GET 请求需要加 @SpringQueryMap,POST 请求使用 @RequestBody

自定义 Feign 配置

Feign允许运行自定义配置来覆盖默认配置,常用的配置如下:

类型 作用 说明
feign.Logger.Level 修改日志级别 最常用。包含:NONE、BASIC、HEADERS、FULL
feign.codec.Decoder 响应结果解析器 HTTP -> Java 对象
feign.codec.Encoder 请求参数编码 Java 对象 -> HTTP请求参数
feign.Contract 支持的注解格式 默认 SpringMVC,也可配置为 Feign 原生注解
feign.Retryer 失败重试机制 默认不重试(即Retryer.NEVER_RETRY),依赖 Ribbon 重试

配置日志级别

默认日志级别是 NONE,不打印任何日志。开发调试建议设为 FULLBASIC

方式一:配置文件(YAML)

  • 全局生效

    (所有 FeignClient 都生效):

    feign:client:config:default: # 这里写 default 表示全局配置loggerLevel: FULL
    
  • 局部生效

    (指定服务生效):

    feign:client:config:userservice: # 这里写具体服务名称loggerLevel: FULL
    

方式二:Java 代码方式

首先声明配置类(不需要@Configuration 注解,避免自动扫包导致全局生效):

public class FeignClientConfiguration {@Beanpublic Logger.Level feignLogLevel() {return Logger.Level.BASIC; }
}
  • 全局配置

    (在启动类注解中指定):

    @EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)
    
  • 局部配置

    (在具体的 Client 接口注解中指定):

    @FeignClient(value = "userservice", configuration = FeignClientConfiguration.class)
    

Feign 的性能优化(重要)

默认的 Feign 只是一个声明式客户端,它只负责把注解转换成 HTTP 请求,实际发送请求依赖底层的委托客户端

底层客户端对比

  1. URLConnection(默认):
    • JDK 自带,每次请求都会建立新的连接,用完即销毁。
    • 不支持连接池,性能较差,频繁的三次握手四次挥手。
  2. Apache HttpClient(推荐):
    • 广泛使用,支持连接池,复用连接。
  3. OKHttp(推荐):
    • 谷歌出品,轻量级,支持连接池

优化步骤:使用连接池(以 HttpClient 为例)

第 1 步:引入依赖

在 POM 文件中添加 HttpClient 依赖,替代默认的 URLConnection:

<!-- httpClient 的依赖 -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId>
</dependency>

第 2 步:在 YAML 中配置连接池

引入依赖后,Feign 默认就会检测并使用 HttpClient,但我们需要开启并配置参数:

feign:httpclient:enabled: true # 开启 feign 对 HttpClient 的支持max-connections: 200 # 最大连接数max-connections-per-route: 50 # 每个路径的最大连接数

4.3 优化总结

  1. 日志级别:生产环境建议使用 BASICNONE,不要用 FULL(影响性能)。
  2. 连接池:务必引入 HttpClientOKHttp 并配置连接池参数。

Feign 的最佳实践

在使用 Feign 时,消费者(Client)和提供者(Controller)的方法签名、URL 是一模一样的,如何避免重复代码?

方式一:继承方式(不推荐)

  • 做法:定义一个统一的 API 接口,Controller 实现该接口,FeignClient 也继承该接口。
  • 缺点:
    • 紧耦合:Consumer 和 Provider 共享了接口,参数修改会影响双方。
    • 参数注解兼容性:SpringMVC 的部分注解在继承时无法完美传递(如 @PathVariable 必须显式指定名称)。

方式二:抽取方式(推荐)

  • 做法:将 FeignClient 接口、POJO(实体类)、DTO 等公共代码抽取成一个独立的 Module(例如叫 feign-api)。
  • 好处:服务与服务之间解耦,复用性高。

操作步骤:

  1. 创建 Module:创建一个名为 feign-api 的模块。

  2. 引入依赖

    <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  3. 编写代码:把 UserClient.java, User.java, FeignConfig.java 等剪切到该模块中。

  4. 消费方引用:在 order-service 中引入 feign-api 的依赖。

  5. 解决扫描问题

    此时,因为 Client 在另一个包下,order-service 的启动类默认扫描不到 feign-api 中的 Client。

    解决方法 A(指定扫描的包):

    @EnableFeignClients(basePackages = "cn.itcast.feign.clients")
    

    解决方法 B(指定具体的 Client 字节码):

    @EnableFeignClients(clients = {UserClient.class})
    

进阶:Feign 与 Hystrix/Sentinel 整合

Feign 可以配合熔断降级组件(通常是 Sentinel 或 Hystrix)使用,确保服务调用失败时有兜底逻辑。

开启 Sentinel 支持

在 YAML 中配置:

feign:sentinel:enabled: true

编写失败降级逻辑

方式一:FallbackClass

实现 FeignClient 接口,内部写降级逻辑。

@Component
public class UserClientFallback implements UserClient {@Overridepublic User findById(Long id) {return new User(); // 返回空对象或默认值}
}

在使用时指定:

@FeignClient(value = "userservice", fallback = UserClientFallback.class)

方式二:FallbackFactory(推荐,可获取异常信息)

@Component
@Slf4j
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {@Overridepublic UserClient create(Throwable throwable) {return new UserClient() {@Overridepublic User findById(Long id) {log.error("查询用户失败,异常信息:", throwable);return new User(); // 降级逻辑}};}
}

在使用时指定:

@FeignClient(value = "userservice", fallbackFactory = UserClientFallbackFactory.class)

总结

使用 Feign 的核心流程:

  1. 导包:OpenFeign, (HttpClient)
  2. 开启@EnableFeignClients
  3. 定义@FeignClient 接口
  4. 配置:
    • 日志:YAML 或 Java Config (Logger.Level)
    • 连接池:YAML 配置 HttpClient
  5. 优化架构:抽取独立的 feign-api 模块。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/989262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gemini 2.5 Flash / Nano Banana 系统提示词泄露:全文解读+安全隐患分析

本文作者找到了一种方法可以深入 Nano Banana 的内部运作机制,具体手法没法公开,但结果可以分享。 破解图像生成器跟破解文本模型完全是两回事。图像模型的设计目标是输出图片而非文字,对提示词注入的响应模式不同。…

S6 All System OBD Scanner: 28 Resets (IMMO/BMS/TPMS/ABS) + Lifetime Free Scans

Modern Car Diagnostics: Solving the Puzzle of Complex Systems In today’s automotive world, European and American vehicles are equipped with sophisticated electronic systems—from engine control units …

第五十六篇

今天是12月5号,上了形策

Linux中级のSSH远程连接

SSH基本概述 SSH是一个安全协议,在进行数据传输时,会对数据包进行加密处理,加密后再进行数据传输。确保了数据传输安全。SSH服务主要有哪些功能? 1.提供远程连接服务器的服务 2.对传输的数据进行加密除了SSH协议能…

Qt C++ 软件开发工程师面试题 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

C 语言 Day02

C 语言 Day02 回顾 1 运行环境搭建 mingw64 配置环境变量(path) vscode 安装 vscode 扩展: 简体中文、c/c++2 编写第一个程序 3 程序运行流程机制 编写代码 -> 预处理 -> 编译 -> 汇编 …

不再错过任何销售:为你的Python Flask应用集成Stripe支付和Slack通知

本文提供了一个详细、循序渐进的实践指南,讲解如何为你的Flask Web应用程序添加一次性的Stripe支付功能,并通过设置Slack Webhook来实现实时销售通知,确保你不再错过任何一笔交易。不再错过任何销售:为你的Python …

LLL格基约简算法(2)

LLL 算法教程:从理论到实践LLL 算法教程:从理论到实践 Date: December 4, 2025目录 第一部分:理论基础LLL 算法概述格的数学基础Gram-Schmidt 正交化LLL 算法的理论框架第二部分:算法实现LLL 算法详细步骤算法正确…

Accurate Camera Calibration using Iterative Refinement of Control Points

基于控制点迭代优化的精确相机标定基于控制点迭代优化的精确相机标定 安库尔达塔(Ankur Datta)、金俊植(Jun-Sik Kim)、武居功(Takeo Kanade) 卡内基梅隆大学机器人研究所 {ankurd,kimjs,tk}@cs.cmu.edu 摘要 本…

探寻并预防机器学习模型中的安全漏洞

文章探讨了机器学习模型在面临对抗性攻击时的脆弱性,如微小的输入扰动即可导致图像识别系统失效。研究同时提出了多种防御策略,包括通过差分隐私保护图结构数据、使用“教师判别器”生成可扩展的私密数据,以及开发能…

国家智库发文回应AI就业焦虑:替代之外,人机协作、灵活就业是趋势

今年8月,国务院发布《关于深入实施“人工智能+”行动的意见》,勾勒出AI技术与产业深度融合的未来蓝图;近日,学习时报刊发的《积极应对人工智能对就业的影响》一文,这份“国家级就业指南”回应了当前大众对于AI抢饭…

实用指南:MySQL 基础完全指南(视频教程)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

12/5

今天没课

实用指南:中国机器人产业:迅猛崛起与未来征程

实用指南:中国机器人产业:迅猛崛起与未来征程2025-12-05 22:19 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display:…

解决国内Github.com打不开的方法

解决国内Github.com打不开的方法解决国内Github.com打不开的方法一、Github是什么github对普通人来说更像是一个巨大的资源库,有丰富的软件资源、各类插件、设计资源等。二、如何访问Github1. 访问错误的原因我们会发…

Harmony鸿蒙编写0基础入门到精通Day11--TypeScript篇

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年下半年上海ISO三体系认证机构全方位评测与选择指南

摘要 随着2025年企业国际化进程加速,ISO三体系认证(ISO9001、ISO14001、ISO45001)成为上海地区企业提升管理水平和市场竞争力的关键。行业数据显示,2024年上海ISO认证市场规模同比增长15%,预计2025年下半年需求将…

鲜花

习惯了 空欢喜 学会了 不哭泣 每颗珍珠都曾是痛过的沙粒 我在等你 找到你 一直到太阳升起 多少次坠下谷底也能抱住自己 山上的风 地心的力 生命向上长成了自己 那时你会看到春野漫地 从失眠 到失意 从失落 到失去 多少…

常用adb+hdc指令

adb指令 查看连接设备adb devices 导出logcat日志adb logcat > 本地路径/logcat.txt 开启/关闭wifi(需要root)adb shell svc wifi disable/enable 打开应用adb shell am start 包名/Activity 关闭应用adb shell am …