当前位置: 首页 > news >正文

十、Feign客户端

目录

1、在springcloud-order项目中引入Feign客户端的依赖

2、在server-order服务的启动类中添加注解@EnableFeignClients

3、使用@FeignClient注解声明Feign客户端需要调用的远程接口

3.1、server-pay服务提供远程接口Controller

3.2、server-member服务提供远程接口Controller

3.3、创建IPayService接口,映射需要调用的pay服务提供的远程接口

3.4、创建IMemberService接口,映射需要调用的member服务提供的远程接口

3.5、在controller中注入接口bean对象,通过调用方法的形式直接调用服务提供者提供的远程接口,更符合开发习惯

3.6、启动服务server-member、server-pay、server-order及server-eureka注册中心

4、OpenFeign客户端对参数的接收

4.1、使用注解@RequestBody接收对象VO参数,否则接收不到传过来的参数

4.2、使用注解@RequestParam("xxx")接收一个普通参数(String/Integer)

4.2.1、在服务提供方和服务调用方提供同样的注解@RequestParam("xxx")

4.2.2、服务提供方不添加@RequestParam("xxx")注解,服务调用方添加@RequestParam("xxx")注解,但是xxx要与服务提供方的参数一致才能映射

4.3、使用@PathVariable接收RESTFul请求路径上的参数

5、FeignClient优雅的使用方式

5.1、在父目录springcloud下创建聚合项目springcloud-api作为公共模块

5.2、在springcloud-api项目的pom文件中引入依赖

5.3、在springcloud-api项目里添加vo对象类和接口

5.4、Maven install项目到maven本地仓库

5.5、在服务提供方server-member和服务调用方server-order引入公共服务模块

5.6、server-member服务端(服务提供方)定义MemberController2 实现api项目中定义的接口

5.7、server-order客户端(服务调用方)定义接口继承api项目中定义的接口


在项目开发中一般访问远程服务接口时并不使用RestTemplate来做,前面已经演示过了怎么通过RestTemplate来访问远程接口,以及基于eureka注册中心的服务发现机制搭配RestTemplate访问远程接口,而使用Feign客户端来访问远程接口是比较常见的做法,其底层实现原理是RPC远程过程调用,同时feign客户端集成了ribbon

1、在springcloud-order项目中引入Feign客户端的依赖

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

2、在server-order服务的启动类中添加注解@EnableFeignClients

@EnableFeignClients(basePackages = "course.springcloud")

basePackages需要配置openfeign的包扫描路径,扫描FeignClient注解并初始化,如果FeignClient注解的接口和启动类同一个路径下,则不需要配置

3、使用@FeignClient注解声明Feign客户端需要调用的远程接口

注意:接口方法上的注解要与服务提供者提供的注解一致,即请求方式要一致,此外,路径也要一致,否则将映射不到请求

3.1、server-pay服务提供远程接口Controller

@RestController
@RequestMapping("/")
public class PayController {@Value("${server.port}")private int port;@GetMapping("/payInfo")public String getPayInfo() {return "当前端口为:" + port + "this is pay Info";}
}

3.2、server-member服务提供远程接口Controller

@RestController
@RequestMapping("/member")
public class MemberController {@Value("${server.port}")private int port;@GetMapping("/memberInfo")public String memberInfo() {return "当前请求端口为:" + port + "   this is Member Info";}
}

3.3、创建IPayService接口,映射需要调用的pay服务提供的远程接口

// value 配置服务提供者的应用名称或者service id;
// path配置请求的前缀(即服务提供者类上的RequestMapping注解上的路径),// 如果不加这个path前缀,那么方法上的每个请求路径都要写完整请求的路径
@FeignClient(value = "server-pay", path = "/")
public interface IPayService {//该注解要与服务提供者的路径及请求方式保持一致,请求方式是GetMapping、PostMapping还是其他,否则映射不到@GetMapping("/payInfo")String getPayInfo();
}

3.4、创建IMemberService接口,映射需要调用的member服务提供的远程接口

// value 配置服务提供者的应用名称或者service id;
// path配置请求的前缀(即服务提供者类上的RequestMapping注解上的路径)
// 如果不加这个path前缀,那么方法上的每个请求路径都要写完整请求的路径
// 例如下面例子所示:则方法中的GetMapping要写成@GetMapping("/member/memberInfo"),如果方法比较多的话,这么写就比较麻烦
@FeignClient(value = "server-member", path = "/member")
public interface IMemberService {//该注解要与服务提供者的路径及请求方式保持一致,请求方式是GetMapping、PostMapping还是其他,否则映射不到@GetMapping("/memberInfo")String getMemberInfo();
}

3.5、在controller中注入接口bean对象,通过调用方法的形式直接调用服务提供者提供的远程接口,更符合开发习惯

@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate IMemberService iMemberService;@Autowiredprivate IPayService iPayService;//使用OpenFeign访问server-member服务的远程接口 /member/memberInfo@GetMapping("/getMember")public String getMember() {return iMemberService.getMemberInfo();}//使用OpenFeign访问server-pay服务的远程接口 /payInfo@GetMapping("/getPay")public String getPay() {return iPayService.getPayInfo();}
}

3.6、启动服务server-member、server-pay、server-order及server-eureka注册中心

3.7、访问接口localhost:9071/order/getPay

3.8、访问接口 localhost:9071/order/getMember

 

 

4、OpenFeign客户端对参数的接收

4.1、使用注解@RequestBody接收对象VO参数,否则接收不到传过来的参数

在server-order、server-member下新增memberVO.class用来设置和接收参数

如果使用了Lombok插件,可以通过注解@Accessors(chain=true)开启链式编程

设置参数时可以简写为New memberVO().setAge(18).setName("张三")

public class memberVO {private Integer age;private String name;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "memberVO{" +"age=" + age +", name='" + name + '\'' +'}';}
}

在server-member下的MemberController.class添加addMember方法用来处理新增请求。

@RestController
@RequestMapping("/member")
public class MemberController {@PostMapping("/addMember")public String addMember(memberVO memberVO) {System.out.println(memberVO.toString());return "add member success";}
}

在server-order下的IMemberService 接口配置feign客户端请求server-member下的远程接口member/addMember

// value 配置服务提供者的应用名称或者service id;
// path配置请求的前缀(即服务提供者类上的RequestMapping注解上的路径)
@FeignClient(value = "server-member", path = "/member")
public interface IMemberService {//该注解要与服务提供者的路径及请求方式保持一致,请求方式是GetMapping、PostMapping还是其他,否则映射不到@GetMapping("/memberInfo")String getMemberInfo();@PostMapping("/addMember")String addMember(memberVO member);
}

在server-order下的OrderController新增接口/order/addMemberInfo以

访问server-member下的远程接口member/addMember

@RestController
@RequestMapping("/order")
public class OrderController {//使用OpenFeign访问server-member服务的远程接口 /member/addMember@GetMapping("/addMemberInfo")public String addMember() {memberVO memberVO = new memberVO();memberVO.setAge(18);memberVO.setName("张三");return iMemberService.addMember(memberVO);}
}

重启server-order、server-member,访问接口localhost:9071/order/addMemberInfo

 

由于member服务下的方法请求参数没有添加注解@RequestBody,所以后台打印出来参数值为null.

加上注解后重启server-member服务后再试一次访问刚刚的接口

 

 可以看到已经接收到了请求传过来的参数了

4.2、使用注解@RequestParam("xxx")接收一个普通参数(String/Integer)

4.2.1、在服务提供方和服务调用方提供同样的注解@RequestParam("xxx")

修改server-member下的MemberController.class添加addMember方法

@PostMapping("/addMember")
public String addMember(@RequestParam("test") Integer suqence,@RequestBody memberVO memberVO) {System.out.println(memberVO.toString());System.out.println(suqence);return "add member success";
}

修改server-order下的IMemberService 接口配置feign客户端请求server-member下的远程接口member/addMember

@PostMapping("/addMember")
String addMember(@RequestParam("test") Integer id, @RequestBody memberVO member);

4.2.2、服务提供方不添加@RequestParam("xxx")注解,服务调用方添加@RequestParam("xxx")注解,但是xxx要与服务提供方的参数一致才能映射

修改server-member下的MemberController.class添加addMember方法

@PostMapping("/addMember")
public String addMember(Integer suqence,@RequestBody memberVO memberVO) {System.out.println(memberVO.toString());System.out.println(suqence);return "add member success";
}

修改server-order下的IMemberService 接口配置feign客户端请求

server-member下的远程接口member/addMember

@PostMapping("/addMember")
String addMember(@RequestParam("suqence") Integer id, @RequestBody memberVO member);

修改OrderControlleraddMember方法测试参数接收

@GetMapping("/addMemberInfo")
public String addMember() {memberVO memberVO = new memberVO();memberVO.setAge(18);memberVO.setName("张三");return iMemberService.addMember(12,memberVO);
}

重启server-member、server-order服务,重新访问接口localhost:9071/order/addMemberInfo

 同一个方法中可以有多个@@RequestParam("xxx")注解,但是只能有一个@RequestBody注解。

4.3、使用@PathVariable接收RESTFul请求路径上的参数

例如:请求路径为/addMember/{id}/{name}

那么方法上的参数就可以写成addMemberInfo(@PathVariable("id")Integer id,@PathVariable("name")String name)

5、FeignClient优雅的使用方式

由于开发项目的时候,在服务提供方和服务调用方有很多重复的代码,如上面演示的VO对象,在server-member和server-order服务下都有,这样造成了代码冗余,维护起来比较繁杂,因此我们可以新增一个公共服务项目,专门处理这些冗余的代码,然后由服务端实现接口,客户端继承接口

5.1、在父目录springcloud下创建聚合项目springcloud-api作为公共模块

5.2、在springcloud-api项目的pom文件中引入依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><scope>provided</scope></dependency>
</dependencies>

5.3、在springcloud-api项目里添加vo对象类和接口

memberVO.class

public class memberVO {private Integer age;private String name;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "memberVO{" +"age=" + age +", name='" + name + '\'' +'}';}
}

IMemberService.class

public interface IMemberService {@GetMapping("/memberInfo")String getMemberInfo();@PostMapping("/addMember")String addMember(@RequestParam("test") Integer id, @RequestBody memberVO member);
}

5.4、Maven install项目到maven本地仓库

 5.5、在服务提供方server-member和服务调用方server-order引入公共服务模块

<dependency><groupId>com.chen</groupId><artifactId>springcloud-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

5.6、server-member服务端(服务提供方)定义MemberController2 实现api项目中定义的接口

@RestController
public class MemberController2 implements IMemberService {@Value("${server.port}")private int port;@Overridepublic String getMemberInfo() {return "当前请求端口为:" + port + "   this is Member Info";}@Overridepublic String addMember(Integer id, memberVO member) {System.out.println(member.toString());System.out.println(id);return "add member success";}
}

5.7、server-order客户端(服务调用方)定义接口继承api项目中定义的接口

目的:为了写@FeignClient注解,并把访问路径补全

@FeignClient(value = "server-member", path = "/member")
public interface IMemberService2 extends IMemberService {}

相关文章:

十、Feign客户端

目录 1、在springcloud-order项目中引入Feign客户端的依赖 2、在server-order服务的启动类中添加注解EnableFeignClients 3、使用FeignClient注解声明Feign客户端需要调用的远程接口 3.1、server-pay服务提供远程接口Controller 3.2、server-member服务提供远程接口Contro…...

登录appuploader

转载&#xff1a;登录appuploader 常规使用登录方法 双击appuploader.exe 启动appuploader 点击底部的未登录&#xff0c;弹出登录框 在登录框内输入apple开发者账号 如果没有apple开发者账号&#xff0c;只是普通的apple账号&#xff0c;请勾选上未支付688 然后软件会提示…...

都别吹牛逼了,2个英语指令简单评测便知ChatGPT、博弈Ai、文心一言、通义千问、讯飞星火真实水平

一、博弈Ai&#xff1a;GPT3.5版 演示&#xff1a;https://chat.bo-e.com/ 1、充当英语发言助手 评分&#xff1a;10分 总结&#xff1a;完整满足了指令需求 2、充当英汉互译器 评分&#xff1a;8分 总结&#xff1a;基本满足了我的指令需求。但是有点啰嗦&#xff0c;扣…...

使用Spring Boot快速搭建项目:减少配置,提升开发效率

使用Spring Boot快速搭建项目&#xff1a;减少配置&#xff0c;提升开发效率 一、Spring Boot简介1 Spring Boot的起源2 Spring Boot的核心特点3 Spring Boot的优势 二、Spring Boot快速搭建项目1 Spring Boot的项目搭建方式使用Spring Initializr创建项目使用Spring Boot CLI创…...

(2)数码管

LED数码管:数码管是一种简单、廉价的显示器&#xff0c;是由多个发光二极管封装在一起组成"8"字器件 51单片机是共阴极连接 74HC245这个芯片有什么作用呢&#xff1f;解&#xff1a;这个芯片被称之为双向数据缓冲器这个芯片的作用&#xff0c;用来进行数据缓冲(提高驱…...

赫夫曼树和赫夫曼编码详解

目录 何为赫夫曼树&#xff1f; 赫夫曼树算法 赫夫曼编码 编程实现赫夫曼树 编程实现赫夫曼编码 编程实现WPL 总代码及分析 何为赫夫曼树&#xff1f; 树的路径长度&#xff1a;从树根到每一结点的路径长度之和 结点的带权路径长度&#xff1a;从树根到该结点的路径长度…...

unity UGUI系统梳理 -交互组件

概述 unity 中的交互组件可用于处理交互&#xff0c;例如鼠标或触摸事件以及使用键盘或控制器进行的交互 1、按钮 (Button) Button详解 2、开关 (Toggle) Background&#xff1a;背景图片&#xff0c;控制toggle组件的背景颜色改变&#xff0c;从而展示此物体是否被选中的…...

HTTP第15讲——HTTP的连接管理

短连接 HTTP 协议最初&#xff08;0.9/1.0&#xff09;是个非常简单的协议&#xff0c;通信过程也采用了简单的“请求 - 应答”方式。 它底层的数据传输基于 TCP/IP&#xff0c;每次发送请求前需要先与服务器建立连接&#xff0c;收到响应报文后会立即关闭连接。 因为客户端与…...

深度剖析Mybatis-plus Injector SQL注入器

背景 在项目中需要同时操作Sql Server 以及 MySQL 数据库&#xff0c;可能平时直接使用 BaseMapper中提供的方法习惯 了&#xff0c;不用的话总感觉影响开发效率&#xff0c;但是两个数据库的SQL语法稍微有点差别&#xff0c;有些暴露的方法并不能直接使用&#xff0c;所以便想…...

【Mysql实战】使用存储过程和计算同比环比

背景 同环比&#xff0c;是基本的数据分析方法。在各类调研表中屡见不鲜&#xff0c;如果人工向前追溯统计数据&#xff0c;可想而知工作量是非常大的。 标题复制10行&#xff0c;并且每行大于10个字符【源码解析】SpringBoot接口参数【Mysql实战】使用存储过程和计算同比环比…...

ChatGPT的前世今生,到如今AI领域的竞争格局,本文带你一路回看!

73年前&#xff0c;“机器思维”的概念第一次被计算机科学之父艾伦图灵&#xff08;Alan Turing&#xff09;提出&#xff0c;从此&#xff0c;通过图灵测试成为了人类在AI领域为之奋斗的里程碑目标。 73年后的今天&#xff0c;在AI历经了数十年的不断进化、迭代后&#xff0c…...

如何在JavaScript中获取当前时间yyyymmddhhmmss? (六种实现方式)

## 介绍 在编写JavaScript代码时&#xff0c;我们经常需要获取当前日期和时间。在本文中&#xff0c;我们将介绍几种获取当前时间并将其格式化为 yyyymmddhhmmss 的字符串的方法。 方法一&#xff1a;使用Date对象 在JavaScript中&#xff0c;我们可以使用 Date 对象来获取当…...

一、走进easyUI的世界

1.什么是easyUI&#xff1f; jQuery EasyUI是一组基于jQuery的UI插件集合体&#xff0c;而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复杂的javascript&#xff0c;也不需要对css样式有深入的了解&#xff0c;开发者需要…...

2023 上半年软件设计师知识点复习总纲

前言&#xff1a;全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;以下简称IT职业资格考试&#xff09;是由中华人民共和国人事部主管&#xff0c;国家计算机网络与信息安全管理中心主办的一项国家级、权威性的计算机职业技能水平认证考试。主要…...

深入理解Java虚拟机:JVM高级特性与最佳实践-总结-3

深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践-总结-3 垃圾收集器与内存分配策略垃圾收集算法标记-清除算法标记-复制算法标记-整理算法 垃圾收集器与内存分配策略 垃圾收集算法 标记-清除算法 最基础的垃圾收集算法是“标记-清除”&#xff08;Mark-Sweep&#xff…...

vue3 cesium datav 可视化大屏

目录 0. 预览效果 1. 代码库包 2. 技术点 3. 一些注意事项&#xff08;配置参数&#xff09; 4. 相关代码详情 0. 预览效果 包含的功能&#xff1a; ① 地球按照一定速度自转 ② 修改加载的geojson面样式 ③ 添加 文字 标注&#xff01; 1. 代码库包 直接采用vue-cli5 创建…...

python内置函数,推导式

abs&#xff1a;取绝对值 data abs&#xff08;-10&#xff09; pow&#xff1a;次方 data pow&#xff08;2&#xff0c;5&#xff09; sum&#xff1a;求和 num_list p[1,2,10,20] res sum(num_list) divmod取商和余数&#xff1a; v1&#xff0c;v2 divmod&…...

【Flink】DataStream API使用之Flink支持的数据类型

Flink的使用过程中&#xff0c;我们的数据都是定义好的 UserBehavior 类型&#xff0c;那还有没有其他更灵活的类型可以用呢&#xff1f;Flink 支持的数据类型到底有哪些&#xff1f; 1. Flink 的类型系统 Flink 作为一个分布式处理框架&#xff0c;处理的是以数据对象作为元…...

QT实现固高运动控制卡示波器

目录 一、固高示波器 二、基于QCustomPlot实现示波器 三、完整源码 一、固高示波器 固高运动控制卡自带的软件有一个示波器功能&#xff0c;可以实时显示速度的波形&#xff0c;可辅助分析电机的运行状态。但是我们基于sdk开发了自己的软件&#xff0c;无法再使用该功能&…...

洛谷P1157详解(两种解法,一看就会)

一、问题引出 组合的输出 题目描述 排列与组合是常用的数学方法&#xff0c;其中组合就是从 n n n 个元素中抽出 r r r 个元素&#xff08;不分顺序且 r ≤ n r \le n r≤n&#xff09;&#xff0c;我们可以简单地将 n n n 个元素理解为自然数 1 , 2 , … , n 1,2,\dot…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...