OpenFeign 远程调用

目录

前言

OpenFeign 介绍

OpenFeign 的前⾝

Spring Cloud Feign

快速上⼿

引⼊依赖

添加注解

编写 OpenFeign 的客户端

远程调⽤

OpenFeign 参数传递

传递单个参数

传递多个参数

传递对象

传递 JSON

最佳实践

Feign 继承⽅式

创建⼀个 Module

引⼊依赖

编写接⼝

打Jar包

服务提供⽅

Feign 抽取⽅式

创建⼀个 module

引⼊依赖

编写 API

打 Jar 包

服务消费⽅使⽤ product-api 

指定扫描类: ProductApi

从本地读取Jar包


前言

        微服务之间的通信⽅式,通常有两种: RPC 和 HTTP. 在 SpringCloud 中,默认是使⽤ HTTP 来进⾏微服务的通信,最常⽤的实现形式有两种:

• RestTemplate

• OpenFeign

        RPC(Remote Procedure Call)远程过程调⽤,是⼀种通过⽹络从远程计算机上请求服务,⽽不需要了解底层⽹络通信细节。RPC 可以使⽤多种⽹络协议进⾏通信,如 HTTP、TCP、UDP等,并且在 TCP/IP⽹络四层模型中跨越了传输层和应⽤层。简⾔之 RPC 就是像调⽤本地⽅法⼀样调⽤远程⽅法。常⻅的 RPC 框架有:

1. Dubbo:Apache Dubbo

 2. Thrift :Apache Thrift - Home

3. gRPC:gRPC

OpenFeign 介绍

        OpenFeign 是⼀个声明式的 Web Service 客户端.它让微服务之间的调⽤变得更简单,类似controller 调⽤ service ,只需要创建⼀个接⼝,然后添加注解即可使⽤ OpenFeign.

OpenFeign 的前⾝

Feign 是 Netflix 公司开源的⼀个组件.

 • 2013年6⽉,Netflix 发布 Feign 的第⼀个版本1.0.0

• 2016年7⽉, Netflix 发布 Feign 的最后⼀个版本 8.18.0 2016年,Netflix将Feign捐献给社区

• 2016年7⽉OpenFeign的⾸个版本9.0.0 发布,之后⼀直持续发布到现在.可以简单理解为 Netflix Feign 是 OpenFeign 的祖先,或者说 OpenFeign 是 Netflix Feign 的升级版. OpenFeign 是 Feign 的⼀个更强⼤更灵活的实现.

Spring Cloud Feign

        Spring Cloud Feign 是 Spring 对 Feign 的封装, 将 Feign 项⽬集成到 Spring Cloud ⽣态系统中.受 Feign 更名影响,Spring Cloud Feign也有两个 starter

        • spring-cloud-starter-feign

        • spring-cloud-starter-openfeign 由于Feign 的停更维护,对应的,我们使⽤的依赖是spring-cloud-starter-openfeign 

OpenFeign 官⽅⽂档:GitHub - OpenFeign/feign: Feign makes writing java http clients easier

Spring Cloud Feign⽂档:Spring Cloud OpenFeign

快速上⼿

引⼊依赖

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

添加注解

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

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

编写 OpenFeign 的客户端

基于 SpringMVC 的注解来声明远程调⽤的信息

package com.bite.order.api;import com.bite.order.model.ProductInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2024-09-22* Time: 0:44*/
@FeignClient(name = "product-service",path = "/product")
public interface ProductApi {@RequestMapping("/info/{productId}")ProductInfo getProductInfoById(@PathVariable("productId") Integer productId);
}

@FeignClient 注解作⽤在接⼝上

参数说明:

 • name/value指定想访问的服务,设置服务的 IP 地址和端口号):指定 FeignClient 的名称,也就是微服务的名称,⽤于服务发现,Feign 底层会使⽤ Spring Cloud LoadBalance进⾏负载均衡.也可以使⽤ url 属性指定⼀个具体的url.

 • pathpath 和  @RequestMapping 组成了接口的路径):定义当前 FeignClient 的统⼀前缀

远程调⽤

        设置好 ProductApi 接口后,通过 ProductApi 的实例调用 getProductInfoById 方法就可以将请求发送给 product-service服务 /product/info/{productId} 路径的接口,并将请求返回的结果赋值给 ProductInfo 类型的对象

package com.bite.order.service;import com.bite.order.api.ProductApi;
import com.bite.order.mapper.OrderMapper;
import com.bite.order.model.OrderInfo;
import com.bite.order.model.ProductInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate ProductApi productApi;public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);ProductInfo productInfo = productApi.getProductInfoById(orderInfo.getProductId());orderInfo.setProductInfo(productInfo);return orderInfo;}
}

        通过上述代码可以看出,通过 OpenFeign 来远程调用其他微服务的接口就像调用本地方法一样,非常的优雅

OpenFeign 参数传递

        通过观察,我们也可以发现,Feign 的客户端和服务提供者的接⼝声明⾮常相似上⾯例⼦中,演⽰了 Feign 从URL中获取参数,接下来演⽰下 Feign 参数传递的其他⽅式

传递单个参数

服务提供⽅ product-service

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

Feign 客户端

        通过 OpenFeign 发送的 http 请求的参数要放到 query string 中,加上注解 @RequestParam 标注

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

注意:@RequestParam 做参数绑定, 不能省略

服务消费⽅ order-service

@RequestMapping("/feign")
@RestController
public class TestFeignController {@Autowiredprivate ProductApi productApi;@RequestMapping("/o1")public String o1(Integer id){return productApi.p1(id);}
}

        自我理解:在 product-service 上有一些接口,order-service 需要访问,按照 OpenFeign 的要求设置好接口,设置了要访问接口的 IP 地址,端口号,路径,由于参数要设置在 HTTP 请求的 query string 处,所以接口的参数前要加上:@RequestParam 注解,OpenFeign 就会在构造 http 请求时将参数放到 query string 处。

传递多个参数

使⽤多个 @RequestParam 进⾏参数绑定即可

服务提供⽅product-service

@RequestMapping("/p2")
public String p2(Integer id,String name){return "p2接收到参数,id:"+id +",name:"+name;
}

Feign 客户端

@RequestMapping("/p2")
String p2(@RequestParam("id")Integer id,@RequestParam("name")String name);

服务消费⽅ order-service

@RequestMapping("/o2")
public String o2(@RequestParam("id")Integer id,@RequestParam("name")String 
name){return productApi.p2(id,name);
}

传递对象

服务提供⽅ product-service

@RequestMapping("/p3")
public String p3(ProductInfo productInfo){return "接收到对象, productInfo:"+productInfo;
}

Feign 客户端

        使用 @SpringQueryMap 将商品信息放到 http 请求的 query string 中发送给接口

@RequestMapping("/p3")
String p3(@SpringQueryMap ProductInfo productInfo);

服务消费⽅order-service

@RequestMapping("/o3")
public String o3(ProductInfo productInfo){return productApi.p3(productInfo);
}

传递 JSON

服务提供⽅ product-service

        加上 @RequestBody 注解表示要接收 http 请求 body 中 json 格式的内容

@RequestMapping("/p4")
public String p4(@RequestBody ProductInfo productInfo){return "接收到对象, productInfo:"+productInfo;
}

Feign 客户端

        加上 @RequestBody 注解表示将 productInfo 的信息以 json 格式放到 body 中

@RequestMapping("/p4")
String p4( ProductInfo productInfo);

服务消费⽅ order-service

@RequestMapping("/o4")
public String o4(@RequestBody ProductInfo productInfo){System.out.println(productInfo.toString());return productApi.p4(productInfo);
}

最佳实践

        最佳实践,其实也就是经过历史的迭代,在项⽬中的实践过程中,总结出来的最好的使⽤⽅式.通过观察,我们也能看出来,Feign 的客户端与服务提供者的 controller 代码⾮常相似

Feign 客户端

@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {@RequestMapping("/{productId}")ProductInfo getProductById(@PathVariable("productId") Integer productId);
}

服务提供⽅ Controller

@RequestMapping("/product")
@RestController
public class ProductController {@RequestMapping("/{productId}")public ProductInfo getProductById(@PathVariable("productId") Integer productId){//...}
}

有没有⼀种⽅法可以简化这种写法呢?

Feign 继承⽅式

        Feign ⽀持继承的⽅式,我们可以把⼀些常⻅的操作封装到接⼝⾥.我们可以定义好⼀个接⼝,服务提供⽅实现这个接⼝,服务消费⽅编写 Feign 接⼝的时候, 直接继承这个接⼝

创建⼀个 Module

接⼝可以放在⼀个公共的Jar包⾥,供服务提供⽅和服务消费⽅使⽤

引⼊依赖

        引入 spring boot 和 open feign 的依赖

<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>

编写接⼝

        在 product-api 中编写接口 ProductInterface

public interface ProductInterface {@RequestMapping("/info/{productId}")ProductInfo getProductInfoById(@PathVariable("productId") Integer productId);@RequestMapping("/oneParmeter")String oneParmeter(@RequestParam("id") Integer id);@RequestMapping("/getMoreParmeter")String moreParmeter(@RequestParam("id") Integer id,@RequestParam("name")String name);@RequestMapping("/getObject")String getObject(@SpringQueryMap ProductInfo productInfo);@RequestMapping("/getJson")public String getJson(@RequestBody ProductInfo productInfo);
}

⽬录结构如下:

打Jar包

通过 Maven 打包

服务提供⽅

服务提供⽅实现接⼝ ProductInterface 

@RequestMapping("/product")
@RestController
public class ProductController implements ProductInterface {@Autowiredprivate ProductService productService;@RequestMapping("/{productId}")public ProductInfo getProductById(@PathVariable("productId") Integer productId){System.out.println("收到请求,Id:"+productId);return productService.selectProductById(productId);}@RequestMapping("/p1")public String p1(Integer id){return "p1接收到参数:"+id;}@RequestMapping("/p2")public String p2(Integer id,String name){return "p2接收到参数,id:"+id +",name:"+name;}@RequestMapping("/p3")public String p3(ProductInfo productInfo){return "接收到对象, productInfo:"+productInfo;}@RequestMapping("/p4")public String p4(@RequestBody ProductInfo productInfo){return "接收到对象, productInfo:"+productInfo;}
}

服务消费⽅

import com.bite.api.ProductInterface;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(value = "product-service", path = "/product") public interface ProductApi extends ProductInterface {}

Feign 抽取⽅式

        官⽅推荐 Feign 的使⽤⽅式为继承的⽅式,但是企业开发中,更多是把 Feign 接⼝抽取为⼀个独⽴的模块 (做法和继承相似,但理念不同).操作⽅法:将 Feign 的 Client 抽取为⼀个独⽴的模块,并把涉及到的实体类等都放在这个模块中,打成⼀个Jar.服务 消费⽅只需要依赖该 Jar 包即可.这种⽅式在企业中⽐较常⻅,Jar 包通常由服务提供⽅来实现.

创建⼀个 module

引⼊依赖

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

编写 API

        将全部的 open feign 客户端的代码写到到 product-api 模块

打 Jar 包

通过 Maven 打包

服务消费⽅使⽤ product-api 

引⼊依赖(将刚刚打的 jar 包导入)

<dependency><groupId>org.example</groupId><artifactId>product-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

指定扫描类: ProductApi

        指定要使用哪个 open feign 客户端

在启动类添加扫描路径(路径就是 product-api  包中 open feign 客户端 ProductApi 的位置)

@EnableFeignClients(basePackages = {"com.bite.api"})

也可以指定需要加载的Feign客户端

@EnableFeignClients(clients = {ProductApi.class})

完整代码如下:

@EnableFeignClients(basePackages = {"com.bite.api"})
@SpringBootApplication
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
}

从本地读取Jar包

修改 pom ⽂件

<dependency>
<groupId>org.example</groupId>
<artifactId>product-api</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- scope 为system. 此时必须提供systemPath即本地依赖路径. 表⽰maven不会去中央仓库查找依赖 不推荐使⽤-->
<scope>system</scope>
<systemPath>D:/Maven/.m2/repository/org/example/product-api/1.0-SNAPSHOT/product-api-1.0-SNAPSHOT.jar</systemPath>
</dependency>/....
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includeSystemScope>true</includeSystemScope></configuration></plugin></plugins>
</build>

把 D:/Maven/.m2/repository 改为本地仓库的路径

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147681.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

EasyExcel将数据库里面的数据生成excel文件

EasyExcel官方文档 1.在model模块导入依赖 <!-- 生成报表--> <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>4.0.3</version> </dependency> 2.修饰实体类 package…

四叉树碰撞代码

使用raylib 代码来源 https://github.com/seyhajin/flux-samples/blob/master/raylib/quadtree/quadtree.c 原来是视锥碰撞四叉树&#xff0c;经过一周开发变成碰撞检测四叉树可视化 后经过改写 绿色检测 灰色检测 //https://github.com/seyhajin/flux-samples/blob/mast…

【C++篇】走进C++标准模板库:STL的奥秘与编程效率提升之道

文章目录 C STL 初探&#xff1a;打开标准模板库的大门前言第一章: 什么是STL&#xff1f;1.1 标准模板库简介1.2 STL的历史背景1.3 STL的组成 第二章: STL的版本与演进2.1 不同的STL版本2.2 STL的影响与重要性 第三章: 为什么学习 STL&#xff1f;3.1 从手动编写到标准化解决方…

three.js 让阴影更黑更暗

r166 可以通过设置intensity属性来配置每个光源的阴影强度 light.shadow.intensity 3;或者 修改shader THREE.ShaderChunk["shadowmap_pars_fragment"]THREE.ShaderChunk["shadowmap_pars_fragment"].replace( "occlusion clamp( max( hard_sha…

基于深度学习的药品三期OCR字符识别

在药品生产线上,药品三期的喷码与条形码识别是保证药品追溯和安全管理的重要环节。传统的识别方法依赖于人工操作,不仅效率低下且容易出错。随着深度学习技术的不断发展,基于OCR(Optical Character Recognition,光学字符识别)的自动化识别系统逐渐成为主流。本文将以哪吒…

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-17

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-17 1. Large Language Models in Biomedical and Health Informatics: A Review with Bibliometric Analysis H Yu, L Fan, L Li, J Zhou, Z Ma, L Xian, W Hua, S He… - Journal of Healthcare …, 2024 生物…

中国雕塑—孙溟展浅析碑帖《郑文公碑》

中国雕塑——孙溟展浅析碑帖《郑文公碑》 《郑文公碑》上碑 《郑文公碑》 下碑 《郑文公碑》是北魏摩崖刻石&#xff0c;又称是《郑羲碑》&#xff0c;属楷书体&#xff0c;此碑分两块&#xff0c;在山东平度县天柱山的那块称之为“上碑”&#xff0c;上碑全称《魏故中书令秘书…

ONNX模型部署利器ONNXRUNTIME框架

1.ONNXRUNTIME介绍 ONNX格式模型部署兼容性最强的框架 ONNXRUNTIME&#xff0c;基本上不会有算子不支持跟不兼容的情况出现&#xff0c;只要能导出ONNX格式模型&#xff0c;它基本上都能成功加载&#xff0c;成功推理。虽然在CPU速度不及OpenVINO、GPU上速度不及TensorRT&#…

RK3588NPU驱动版本升级至0.9.6教程

RK3588NPU驱动版本升级至0.9.6教程 1、下载RK3588NPU驱动2、修改NPU驱动源码2.0 修改MONITOR_TPYE_DEV写错问题2.1 解决缺少函数rockchip_uninit_opp_table问题2.2 解决缺少函数vm_flags_set、vm_flag_clear的问题2.3 内核编译成功2.4 重新构建系统 3、注意事项4、其他问题处理…

智谱清影的魅力:使用CogVideoX-2b生成6秒视频的真实体验!

文章目录 1 3D变分自编码器与3D RoPE2 精确描述与多样化输入3 社区的力量与未来展望 在8月6日&#xff0c;智谱 AI 发布了一则令人振奋的消息&#xff1a;他们决定开源其视频生成模型CogVideoX。 1 3D变分自编码器与3D RoPE 作为一名开发者&#xff0c;我近期才来体验这个新工…

【C++】面向对象编程的三大特性:深入解析继承机制

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriori…

关闭小广告【JavaScript】

在 JavaScript 中实现关闭小广告的功能&#xff0c;可以通过监听点击事件来隐藏广告元素。 实现效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport&q…

IP地址免费SSL证书建议使用吗?

IP地址免费SSL证书的现状 市场情况&#xff1a;目前市面上并没有免费的IP地址SSL证书。即使有少数机构提供所谓的“免费”证书&#xff0c;也可能存在功能限制、有效期短、技术支持不足等问题。 提供机构&#xff1a;尽管没有完全的免费选项&#xff0c;但可以选择一些可信赖的…

基于51单片机的简易8层电梯模拟proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1z4SBpi2yb8Qeu-85jqkuZQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…

实用为主,需求为王!通风天窗专业厂家谈谈通风天窗怎么选?

通风天窗作为现代建筑的重要组成部分&#xff0c;不仅能够有效改善室内空气质量&#xff0c;还能增强建筑的自然采光与美观性。市场上通风天窗种类繁多&#xff0c;品质参差不齐&#xff0c;如何选购一款既满足功能需求又性价比高的产品&#xff0c;成为业主关注的焦点。成都昱…

图为科技大模型一体机,智领未来社区服务

当AI与边缘计算相遇&#xff0c;一幅关于智慧生活的宏伟蓝图正缓缓展开。 今天&#xff0c;让我们一同探索&#xff0c;如何通过图为大模型一体机&#xff0c;为物业服务插上智能的翅膀。 通过整合采集物业数据&#xff0c;大模型一体机可全方位为物业行业赋能&#xff0c;实…

【SpringBoot详细教程】-02-SpringBoot配置【持续更新】

Hello&#xff01;彦祖们&#xff0c;从今天开始我将更新一波超详细的SpringBoot的图文教程&#xff0c;感兴趣的老铁给个关注点赞 支持一下呗&#xff0c;最好再评论一个666&#xff0c;O(∩_∩)O哈哈~&#xff08;贪心了&#xff09; 点个关注吧 02. SpringBoot配置 Sprin…

图像放大效果示例【JavaScript】

实现效果&#xff1a; 当鼠标悬停在小图&#xff08;缩略图&#xff09;上时&#xff0c;大图&#xff08;预览图&#xff09;会随之更新为相应的小图&#xff0c;并高亮当前悬浮的小图的父元素。 代码&#xff1a; 1. HTML部分 <!DOCTYPE html> <html lang"z…

[Excel VBA]如何使用VBA自动生成图表

在Excel中&#xff0c;图表是可视化数据的重要工具。以下是一个VBA代码示例&#xff0c;帮助你自动生成图表。 1. 代码说明 该代码会根据指定数据范围创建一个柱状图&#xff0c;并设置图表的基本属性。 2. VBA代码 Sub CreateChart()Dim ws As WorksheetDim chartObj As Ch…

转行要趁早!网络安全岗人才稀缺,前景广阔,零基础入门到精通,收藏这篇就够了

1 网络安全从业人员能力基本要求&#xff0c;您达标了吗&#xff1f; 引导 根据国家市场监督管理总局、国家标准化管理委员会发布中华人民共和国国家标准公告&#xff08;2023年第1号&#xff09;&#xff0c;由全国信息安全标准化技术委员会归口的《信息安全技术 网络安全从业…