[Spring] OpenFeign的使用

ops/2025/1/23 11:30:18/

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (93平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. RestTemplate存在的问题
  • 2. OpenFeign介绍
    • 2.1 引入依赖
    • 2.2 添加注解
    • 2.3 编写OpenFeign客户端
    • 2.4 远程调用
    • 2.5 测试
  • 3. OpenFeign参数传递
    • 3.1 传递单个参数
    • 3.2 传递多个参数
    • 4.3 传递对象
    • 3.4 传递Json
  • 4. 最佳实践
    • 4.1 Feign继承方式
    • 4.2 Feign抽取方式

1. RestTemplate存在的问题

观察我们之前远程调用的代码

java">public OrderInfo selectOrder(Integer id){OrderInfo orderInfo = orderMapper.selectOrderById(id);//把获取到的服务URL拼接到远程调用的URL中String url = "http://product-service/product/select?id=" + orderInfo.getProductId();ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;
}

虽然说RestTemplate对HTTP封装之后,已经比直接使用HTTP Client方便很多,但是还是存在一些问题的.

  1. 需要拼接URL,灵活性高,但是封装臃肿,URL复杂的时候,容易出错.
  2. 代码可读性差,风格不统一.

微服务之间的通行主要有两种方式,一种是RPC,一种是HTTP.在SpringCloud中,默认是使用HTTP进行通信的,最常用的实现形式有两种:

  • RestTemplate
  • OpenFeign

接下来我们就来详细介绍一下OpenFeign.

2. OpenFeign介绍

OpenFeign是一个声明式的Web Service客户端.它让微服务之间的调用变得更加简单,类似与Controller调用Service,只需要创建一个接口,然后再添加注解就可以使用OpenFeign.

2.1 引入依赖

首先我们需要在服务调用方(order-service)中引入依赖

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

2.2 添加注解

在order-service的启动类添加注解,@EnableFeignClients,开启OpenFeign的功能.

java">@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class,args);}
}

2.3 编写OpenFeign客户端

在调用其他服务的客户端之下,编写API调用接口,基于SpringMVC的注解来声明远程调用的信息.
在这里插入图片描述

java">@FeignClient(name = "product-service")
public interface ProductApi {@RequestMapping("/product/select")ProductInfo getProductInfo(@RequestParam("id")Integer id);
}

[注意]:在接口的参数前面必须使用@RequestParam加上所调用服务接口的对应参数,否则参数无法传入,就相当于在请求的后面加上了?参数=xxx.
在这里插入图片描述

也可以把该服务的接口的统一前缀(放在类上的@RequestMapping)统一放到FeignClient注解的Path参数中.

java">@FeignClient(name = "product-service",path = "/product")
public interface ProductApi {@RequestMapping("/select")ProductInfo getProductInfo(@RequestParam("id")Integer id);
}

@FeignClient注解作用在接口上,参数说明:

  • name/value: 指定OpenFeign的名称,也就是被调用的微服务的名称,用于服务发现,Feign底层会使用SpringLoadBalance进行负载均衡.
    当然也可以使用URL属性指定一个具体的URL.
  • Path: 定义当前FeignClient的统一前缀,一般是被调用方Controller层的类注解.

2.4 远程调用

修改远程调用方法

java">@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate ProductApi api;//设置原子类public OrderInfo selectOrder(Integer id){OrderInfo orderInfo = orderMapper.selectOrderById(id);//把获取到的服务URL拼接到远程调用的URL中Integer productId = orderInfo.getProductId();ProductInfo productInfo = api.getProductInfo(productId);orderInfo.setProductInfo(productInfo);return orderInfo;}
}

2.5 测试

启动服务.访问接口,测试远程调用.
在这里插入图片描述

3. OpenFeign参数传递

3.1 传递单个参数

我们上面2.4的例子就是单个参数的调用.下面我们再来举一个例子

  1. 服务提供方product-service
java">@RestController
@RequestMapping("/product")
public class ProductController {@RequestMapping("/p1")public String p1(Integer id){return "接收到参数"+id;}
}
  1. FeginClient
java">@FeignClient(value = "product-service")
public interface ProductApi {@RequestMapping("/product/p1")String p1(@RequestParam("id") Integer id);
}

和我们上面提到的一样,@RequestParam是用来做参数绑定的,不能省略.
3. order-service

java">@RequestMapping("/order")
@RestController
public class OrderController {@Autowiredprivate ProductApi api;@RequestMapping("/p1")public String p1(Integer id){return api.p1(id);}
}

远程测试调用:GET http://127.0.0.1:8080/order/p1?id=1
在这里插入图片描述

3.2 传递多个参数

使用多个@RequestParam进行参数绑定即可

  1. 服务提供方product-service
java">@RestController
@RequestMapping("/product")
public class ProductController {@RequestMapping("/p2")public String p2(Integer id1,Integer id2){return "接收到参数1:" + id1 + ",接收到参数2:" + id2;}
}
  1. FeignClient
java">@FeignClient(value = "product-service")
public interface ProductApi {@RequestMapping("/product/p2")String p2(@RequestParam("id1") Integer p1,@RequestParam("id2") Integer p2);
}
  1. 服务消费方order-service
java">@RequestMapping("/order")
@RestController
public class OrderController {@Autowiredprivate ProductApi api;@RequestMapping("/p2")public String p2(Integer p1,Integer p2){return api.p2(p1,p2);}
}

调用接口进行测试:GET http://127.0.0.1:8080/order/p2?p1=1&p2=2
在这里插入图片描述

4.3 传递对象

  1. 服务提供方product-service
java">@RequestMapping("/p3")
public String p3(ProductInfo productInfo){return "接收到对象:" + productInfo;
}
  1. Feign
java">@RequestMapping("/product/p3")
String p3(@SpringQueryMap ProductInfo productInfo);

其中@SpringQueryMap注解表示的是:可以方便地将一个对象的属性作为请求的查询参数添加到请求的 URL中,避免了手动构建查询参数字符串(如json)的繁琐过程.
3. order-service

java">@RequestMapping("/p3")
public String p3(ProductInfo productInfo){return api.p3(productInfo);
}

测试远程调用:GET http://127.0.0.1:8080/order/p3?id=5&productName=zhangsan
在这里插入图片描述

3.4 传递Json

和我们之前学习SpringBoot的时候一样,同样是使用@RequestBody注解进行绑定.
注意由于数据在服务之间一直是按照Json格式传递的,所以服务方,服务调用方,FeignClient的参数上都需要加上注解.

  1. 服务提供方product-service
java">@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){return "接收到对象:" + productInfo;
}
  1. FeignClient
java">@RequestMapping("/product/p4")
String p4(@RequestBody ProductInfo productInfo);
  1. 服务消费方order-service
java">@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){return api.p4(productInfo);
}

测试远程调用:http://127.0.0.1:8080/order/p4
在这里插入图片描述

4. 最佳实践

通过观察,我们也能看出来,Feign的客户端与服务提供者的controller代码非常相似.
Feign客户端:

java">@FeignClient(value = "product-service")
public interface ProductApi {@RequestMapping("/product/p1")String p1(@RequestParam("id") Integer id);
}

服务提供方Controller

java">@RestController
@RequestMapping("/product")
public class ProductController {@RequestMapping("/p1")public String p1(Integer id){return "接收到参数"+id;}
}

有没有一种方法可以简化这种写法呢?

4.1 Feign继承方式

Feign支持继承的方式,我们可以把一些常见的操作封装到接口里.
我可以定义好一个接口,服务提供方实现这个接口,服务消费方编写Feign接口的时候,直接继承这个接口.
接口可以放在一个公共的jar包中,供服务提供方和服务消费方使用.

  1. 新建一个模块
    在这里插入图片描述
  2. 引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
</dependencies>
  1. 编写接口
    复制ProductInfo类和ProductApi到product-api模块中.把ProductApi改名为ProductInterface
    在这里插入图片描述
  2. 打jar包,并安装到本地Maven仓库
    在这里插入图片描述
    点击install.该模块就会被安装到本地的Maven仓库.
    在这里插入图片描述
    由于jar包中已经有了ProductInfo类,所以我们就可以把product-service和order-service的ProductInfo类注掉了.
  3. 服务提供方
    需要先在服务方中引入对应模块的依赖.
<dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope>
</dependency>

服务方product-service直接实现接口ProductInterface.

java">@RestController
@RequestMapping("/product")
public class ProductController implements ProductInterface {@Autowiredprivate ProductService productService;@RequestMapping("/select")public ProductInfo getProductInfo(Integer id){return productService.selectById(id);}@RequestMapping("/p1")public String p1(Integer id){return "接收到参数"+id;}@RequestMapping("/p2")public String p2(Integer id1,Integer id2){return "接收到参数1:" + id1 + ",接收到参数2:" + id2;}@RequestMapping("/p3")public String p3(ProductInfo productInfo){return "接收到对象:" + productInfo;}@RequestMapping("/p4")public String p4(@RequestBody ProductInfo productInfo){return "接收到对象:" + productInfo;}
}
  1. 服务消费方
    同样,首先先添加依赖.
    之后让FeignClient继承ProductInterface
java">@FeignClient(value = "product-service")
public interface ProductApi extends ProductInterface {}

注意在上述步骤中,把ProductInfo类引入包的路径全部改为之前打包的product-api模块下ProductInfo类的路径.

  1. 测试接口
    http://127.0.0.1:8080/order/select?id=1
    在这里插入图片描述

4.2 Feign抽取方式

官方推荐Feign的使用方式为继承的方式,但是企业开发中,更多是把Feign接口抽取为⼀个独立的模块(做法和继承相似,但理念不同).
操作方法:
将Feign的Client抽取为⼀个独立的模块,并把涉及到的实体类等都放在这个模块中,打成⼀个Jar.服务消费方只需要依赖该Jar包即可.这种方式在企业中比较常见,Jar包通常由服务提供方来实现.
前4步和前面继承的方式一样.只不过接口ProductApi在复制到新模块的时候不用修改名字
在这里插入图片描述

  1. 服务消费方使用product-api
    首先引入依赖,之后把该模块中原有的ProductApi接口注掉.
<dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

之后指定扫描类
在启动类中添加需要加载的Feign客户端.

java">@SpringBootApplication
@EnableFeignClients(clients = ProductApi.class)
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class,args);}
}
  1. 测试
    远程调用接口http://127.0.0.1:8080/order/select?id=1
    在这里插入图片描述

http://www.ppmy.cn/ops/152450.html

相关文章

MySQL 窗口函数

MySQL 窗口函数 1&#xff0c;窗口函数 1.1&#xff0c;什么是窗口函数1.2&#xff0c;基本语法 2&#xff0c;函数详解 2.1&#xff0c;聚合函数2.2&#xff0c;排序函数2.3&#xff0c;偏移函数2.4&#xff0c;值函数 3&#xff0c;进阶用法 1&#xff0c;窗口函数 1.1&am…

PHP校园助手系统小程序

&#x1f511; 校园助手系统 —— 智慧校园生活 &#x1f4f1;一款基于ThinkPHPUniapp框架深度定制的校园助手系统&#xff0c;犹如一把智慧之钥&#xff0c;专为校园团队精心打造&#xff0c;解锁智慧校园生活的无限精彩。它独家适配微信小程序&#xff0c;无需繁琐的下载与安…

mysql数据被误删的恢复方案

文章目录 一、使用备份恢复二、使用二进制日志&#xff08;Binary Log&#xff09;三、使用InnoDB表空间恢复四、使用第三方工具预防措施 数据误删是一个严重的数据库管理问题&#xff0c;但通过合理的备份策略和使用适当的恢复工具&#xff0c;可以有效地减少数据丢失的风险…

用着很顺手的电脑亮度随心随意调节

一、功能介绍 显示高级设置&#xff0c;可以调节屏幕RGB色彩。 娱乐亮度&#xff0c;一键娱乐亮度调节。 护眼亮度&#xff0c;保护眼睛&#xff0c;减少蓝光。 恢复正常&#xff0c;一键恢复到默认模块。 二、问题解答 1、亮度更改后显示器无变化&#xff01;软件根本都没…

Glarysoft Malware Hunter 多语检测和删除各种恶意软件和间谍软件 v1.195.0.824

Glarysoft Malware Hunter 是一款专业的安全工具&#xff0c;旨在帮助用户检测和删除各种恶意软件和间谍软件。它可以扫描和删除计算机上的病毒、木马、广告软件和其他安全威胁。 软件功能 病毒扫描&#xff1a;Malware Hunter可以快速而全面地扫描计算机&#xff0c;以查找潜…

Springboot3 自动装配之核心文件:imports文件

注&#xff1a;本文以spring-boot v3.4.1源码为基础&#xff0c;梳理spring-boot应用启动流程、分析自动装配的原理 如果对spring-boot2自动装配有兴趣&#xff0c;可以看看我另一篇文章&#xff1a; Springboot2 自动装配之spring-autoconfigure-metadata.properties和spring…

【Unity3D实现雨下在窗户上的效果】

系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、效果展示👉二、原理👉三、使用步骤3-1、shader代码纹理映射数学运算和函数的运用特效算法的实现高效的性能优化👉壁纸分享👉总结👉前言 想要好看的效果肯定是要用shader实现啦,为什么呢? 因为Shade…

Y3编辑器2.0功能指引

文章目录 一、2.0功能概览1.1 地形1.1.1 植被染色1.1.2 3D物理组件和逻辑物理组件染色1.1.3 悬崖创建时自动刷纹理 1.2 成就系统1.3 新ECA1.4 界面拦截和可拖动1.5 音频上限及优先级 二、界面编辑器&#xff1a;元件&#xff08;待补&#xff09;三、AIGC3.1 语音生成3.2 图片生…