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
相关推荐
星火1024几秒前
【Groovy翻译-进阶篇】运行时元编程与编译时元编程(上)
后端·groovy
CHHH_HHH5 分钟前
【Linux系统篇】深入解析Linux文件系统:从磁盘寻址到软硬链接
linux·服务器·开发语言·后端·ubuntu
星火102411 分钟前
【Groovy翻译-进阶篇】运行时元编程与编译时元编程(下)
后端·groovy
用户1069117941012 分钟前
SpringSercuirty整合jwt
后端
岁月如歌778619 分钟前
一次讲透 Redis 缓存击穿、穿透、雪崩,从原理到实战解决方案
java·后端·架构
IT_陈寒29 分钟前
Vue的v-for为啥把我的渲染顺序搞乱套了?
前端·人工智能·后端
用户1069117941029 分钟前
SpringSecuirty自定义接口或者资源权限
后端
AI多Agent协作实战派1 小时前
AI多Agent协作系统实战(四十六):改了十次规则,AI员工还是老样子——会话缓存的坑
java·spring·缓存
天涯明月19931 小时前
SGLang深度研究报告
人工智能·后端·推理·sglang
0xBADCODE1 小时前
Flask SSTI读SECRET_KEY+伪造Session:税务系统渗透全流程
前端·后端·python·安全·web安全·网络安全·flask