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
相关推荐
鶴哥只手遮天20 分钟前
《rustc 内幕》第 1 章 全景:rustc 编译流水线与 crate 版图
后端·rust·开源
starzy199041 分钟前
深入理解Scala隐式值:编译期自动装配
开发语言·后端·scala
liangbo71 小时前
Spring系列11:切点表达式
java·spring
装不满的克莱因瓶2 小时前
设计模式之策略模式核心概念和应用场景
java·后端·设计模式·架构·系统架构·策略模式
特立独行的猫A9 小时前
用仓颉语言 cj-tauri 框架,五分钟给娃做了个鸿蒙形近字游戏
java·后端·python
码事漫谈12 小时前
我花了一周时间,看AI公司怎么"管"AI,结果越看越后背发凉
后端
爱学习的程序媛14 小时前
Python常用框架梳理
开发语言·后端·python·ai·web·后端框架·python框架
GISer_Jing15 小时前
Agent核心内容
后端·ai·langchain
budingxiaomoli16 小时前
Spring统一功能处理
java·后端·spring
某鹏16 小时前
网关选型:Go、Java、Graal 谁都不能完胜
后端