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
相关推荐
下地种菜小叶3 小时前
接口幂等怎么设计?一次讲清重复提交、支付回调、幂等键与防重落地方案
java·spring boot·spring·kafka·maven
浪客川3 小时前
【百例RUST - 011】简单键值对
开发语言·后端·rust
喜欢流萤吖~3 小时前
SpringBoot 性能优化实战
spring boot·后端·性能优化
我登哥MVP3 小时前
【SpringMVC笔记】 - 6 - RESTFul编程风格
java·spring boot·spring·servlet·tomcat·maven·restful
yhole3 小时前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
常利兵3 小时前
Spring Boot 搭建邮件发送系统:开启你的邮件自动化之旅
spring boot·后端·自动化
彭于晏Yan3 小时前
Spring Boot 集成邮件服务实现发送邮件功能
java·spring boot·后端
浮尘笔记3 小时前
Java Snowy 框架生产环境安全部署全流程(服务器篇)
java·运维·服务器·开发语言·后端