SpringCloud Feign 声明式服务调用

一、Feign 是什么?

Feign 是 Spring Cloud 提供的一个声明式 HTTP 客户端,用来简化微服务之间的远程调用。

  • 你只需要写一个接口,加几个注解,就能像调用本地方法一样调用远程服务
  • 它内部已经集成了 Ribbon,自带负载均衡能力

核心优势

代码极度简洁:不用手动拼接 URL、不用自己写 HTTP 请求

自带负载均衡:和 Ribbon 无缝集成,支持轮询、随机等策略

支持 Spring MVC 注解:@RequestMapping、@RequestParam、@PathVariable 等都能用

Feign 与 Ribbon / 负载均衡的关系

Feign 内部默认集成了 Ribbon,自带负载均衡能力

你不需要手动给 RestTemplate 加 @LoadBalanced,Feign 已经帮你做好了

默认负载均衡策略是轮询,也可以自定义策略:

二,使用feign

创建文件 四个工程

创建接口

feign_consumer

在启动类 添加 EnableFeignClients 注解 扫描 Feign的注解 @FeignClient("feign-provider")

@Autowired

private UserFeign userFeign; 只需要这一个就行

在启动

在访问 consumer的 路径就会跳转 common1和common2 的内容了

三,feign的原理

1、@EnableFeignClients开启feign注解的支持:FeignClientsRegistrar.registerFeignClients():扫描被@FeignClient标识的接口并生成代理类交给spring容器管理

2、为接口方法创建requestTemplate:当consumer调用feign的代理类时,代理类会调用SynchronousMethodHandler.invoke()创建requestTemplate

四、feign的传参方式

1、?传参

@RequestParam("sb"):url?sb=250
2、restful传参

@PathVariable("sb"):url/{sb}--->url/250

3、pojo传参

@RequestBody:pojo--->json

feign_consumer

java 复制代码
package com.yunkukukukuku.controller;

import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/consumer")
public class ConsumerController {

    @Autowired
    private UserFeign userFeign; // Feign 客户端

    //获取用户信息 {} 传参
     @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id) {
        // 调用 Feign 客户端的方法获取用户信息
        return userFeign.getUserById(id);
    }
    //restful 传参
    @RequestMapping("/getUserById2")
    public User getUserById2( User user) {
        return userFeign.getUserById2(user);
    }
    //? 传参
    @RequestMapping("/getUserById3")
    public User getUserById3(@RequestParam("id") Integer id) {
        // 调用 Feign 客户端的方法获取用户信息
        return userFeign.getUserById3(id);
    }
    //pojo 传参
    @RequestMapping("/getUserById4")
    public List<User> getUserById4() {
        List<User> userList = new ArrayList<>();
            -----
        return userFeign.getUserById4(userList);

    }
}

feign_interface

java 复制代码
package com.yunkukukukuku;

import java.util.List;

@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {
    //获取用户信息 {} 传参
    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable("id") Integer id);//PathVariable 获取路径中的参数
    //restful
    @RequestMapping("/getUserById2")
    User getUserById2( @RequestBody User user);//RequestBody 获取请求体中的参数
    //? 传参
    @RequestMapping("/getUserById3")
    User getUserById3(@RequestParam("id") Integer id);//RequestParam 获取路径中的参数
    //pojo 传参
    @RequestMapping("/getUserById4")
    List<User> getUserById4(List<User> userList);
}

feign_provider_1 controller

java 复制代码
package com.yunkukukukuku.controller;

import java.util.List;
@RestController
@RequestMapping("/provider")
public class ProviderController {
    @Autowired
    private UserService userService;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id) {
        return userService.getUserById(id);
    }
    //restful
    @RequestMapping("/getUserById2")
    public User getUserById2(@RequestBody User user) {
        return userService.getUserById2(user);
    }
    //? 传参
    @RequestMapping("/getUserById3")
    User getUserById3(@RequestParam("id") Integer id) {
        return userService.getUserById3(id);
    }
   //pojo 传参
    @RequestMapping("/getUserById4")
    public List<User> getUserById4(List<User> userList) {
        return userService.getUserById4(userList);
    }
}

五,补充

坑 1:对象参数传参报错(你之前的 IllegalStateException)

  • 问题:Feign 默认会把对象参数当成 @RequestBody 处理,而你的 Provider 端是用 URL 查询参数接收

  • 解决:Feign 接口的对象参数上必须加 @SpringQueryMap,让它自动把对象展开成 ?id=12&name=xxx 格式的 URL 参数

坑 2:@PathVariable 不加参数名报错

  • 问题:Feign 接口中 @PathVariable("id") 必须指定参数名,否则无法绑定路径变量

  • 解决:必须写 @PathVariable("id"),不能省略 "id"

坑 3:@RequestParam 必须指定参数名

  • 问题:Feign 接口中 @RequestParam("id") 必须指定参数名,否则会报错

  • 解决:必须写 @RequestParam("id"),不能省略 "id"

场景 注解 适用请求方式 备注
路径变量 @PathVariable GET 路径中必须有 {变量名}
URL 查询参数(单个) @RequestParam GET/POST 必须指定参数名
URL 查询参数(对象) @SpringQueryMap GET/POST 必须加此注解
请求体 JSON @RequestBody POST/PUT 只能用 POST/PUT,不能用 GET
相关推荐
专业程序开发源6 小时前
springboot社区养老系统44071-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·php·课程设计
小呆呆6666 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
周杰伦fans7 小时前
8GB显存下模型量化实战指南
人工智能·后端·c#
小蒜学长7 小时前
基于SpringBoot的佳新超市管理系统设计与实现系统(代码+数据库+LW)
java·数据库·spring boot·后端·佳新超市管理系统
IT_陈寒8 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
打工仔折腾 AI9 小时前
把AI Agent托管在家用电脑:UU远程终端与端口映射实测记录
人工智能·后端·python·langchain·ai agent 实战
vx_Biye_Design9 小时前
springboot高校选课系统82776-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express
打工仔折腾 AI11 小时前
LLaMA 1 到 LLaMA 3 架构演进拆解:从 RoPE、GQA 到词表扩张
人工智能·后端·python·深度学习·langchain·llama
可乐鸡翅yeah_11 小时前
HLS 分片过期清理,直播旧 TS 分片磁盘爆满问题处理
java·后端·spring·m3u8·m3u8在线·音视频在线播放