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

SpringCloud Alibaba微服务 -- OpenFeign的使用(保姆级)

openFeign的使用

1、openFeign是干什么的?

OpenFeign是一个显示声明式的WebService客户端。使用OpenFeign能让编写Web Service客户端更加简单。使用时只需定义服务接口,然后在上面添加注解。OpenFeign也支持可拔插式的编码和解码器。spring cloud对feign进行了封装,使其支持MVC注解和HttpMessageConverts。和eureka(服务注册中心)和ribbon组合可以实现负载均衡。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求,非常的方便

2、建立服务模块
建立order订单模块服务(之前文章已经建立了user服务),这样两个服务就可以测试feign接口了。

user服务的建立请看第一篇文章 https://blog.csdn.net/qq_38374397/article/details/125542389

新建maven子模块


application.yml配置文件

server:port:9091spring:application:name:mdx-shop-order cloud:nacos:discovery:server-addr:localhost:8848namespace:mdx group:mdx

bootstrap.properties配置文件

spring.application.name=mdx-shop-order spring.cloud.nacos.config.server-addr=localhost:8848spring.cloud.nacos.config.extension-configs[0].data-id=mdx-shop-order.yaml spring.cloud.nacos.config.extension-configs[0].group=shop spring.cloud.nacos.config.extension-configs[0].refresh=truespring.cloud.nacos.config.file-extension=yml spring.cloud.nacos.config.namespace=mdx spring.cloud.nacos.config.group=shop

3、引入依赖

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

4、openFeign的使用

我们先创建一个common的公共模块,然后引入一些工具类

在common中添加工具类,一些字符串操作和非空判断

在其他模块中引用common公共模块

在order服务中先创建一个获取订单号的测试接口
建立一个controller层和service层,controller层代码分别如下:

@RestController@RequestMapping("/order")publicclassOrderController{@AutowiredprivateOrderServiceorderService;@GetMapping("getOrderNo")publicStringgetOrderNo(StringuserId){returnorderService.getOrderNo(userId);}}

service层实现类,目前没有查DB,做了简单的判断

@ServicepublicclassOrderServiceImplimplementsOrderService{@OverridepublicStringgetOrderNo(StringuserId){if(StringUtils.isNotEmpty(userId)&&userId.equals("mdx123456")){return"O111222333444";}return"订单不存在";}}

在启动类开启支持feign的远程调用的注解 @EnableFeignClients

@SpringBootApplication@EnableFeignClientspublicclassMdxShopUserApplication{publicstaticvoidmain(String[]args){SpringApplication.run(MdxShopUserApplication.class,args);}}

然后在user服务中创建一个OrderFeign接口用来调用order服务

@FeignClient(value="mdx-shop-order")@ComponentpublicinterfaceOrderFeign{@GetMapping("order/getOrderNo")StringgetOrderNo(StringuserId);}

@FeignClient标签的常用属性如下:

  • name/value:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
  • url: url一般用于调试,可以手动指定@FeignClient调用的地址
  • decode404:当发生http 404错误时,如果该字段位true,会调用decoder进行解码,否则抛出FeignException
  • configuration: Feign配置类,可以自定义Feign的Encoder、Decoder、LogLevel、Contract
  • fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口
  • fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
  • path: 定义当前FeignClient的统一前缀,当我们项目中配置了server.context-path,server.servlet-path时使用

value 属性的值是order服务的服务名称,也就是注册到注册中心中的服务名称

我们在user服务中建立一个controller和service调用feign接口来测试一下
controller层

@RestController@RequestMapping("/user")publicclassUserController{@AutowiredprivateUserServiceuserService;@GetMapping("getOrderNo")publicStringgetOrderNo(StringuserId){returnuserService.getOrderNo(userId);}}

service层

@ServicepublicclassUserServiceImplimplementsUserService{@AutowiredprivateOrderFeignorderFeign;@OverridepublicStringgetOrderNo(StringuserId){returnorderFeign.getOrderNo(userId);}}

分别启动user服务和order服务测试

启动user服务的时候发现报错了,是因为SpringCloud Feign在Hoxton.M2 RELEASED版本之后抛弃了Ribbon,使用了spring-cloud-loadbalancer,所以我们这里还需要引入spring-cloud-loadbalancer的依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId><version>3.1.1</version></dependency>

重新启动项目,并查看nacos,发现服务已经注册成功

接下来访问user服务,看看是否能通过feign接口成功获取到订单号

user服务报错

feign.FeignException$MethodNotAllowed:[405]during[GET]to[http://mdx-shop-order/order/getOrderNo][OrderFeign#getOrderNo(String)]:[{"timestamp":"2022-07-04T03:13:30.111+00:00","status":405,"error":"Method Not Allowed","path":"/order/getOrderNo"}]

order服务提示信息

2022-07-0411:13:30.110WARN66016---[nio-9091-exec-6].w.s.m.s.DefaultHandlerExceptionResolver:Resolved[org.springframework.web.HttpRequestMethodNotSupportedException:Requestmethod'POST'not supported]

通过意思信息我们可以发现,我们的GET请求被当成了POST请求,如果不加默认的注解,Feign则会对参数默认加上@RequestBody注解,而RequestBody一定是包含在请求体中的,GET方式无法包含

我们改变一下feign接口,添加一个@RequestParam注解

@FeignClient(value="mdx-shop-order")@ComponentpublicinterfaceOrderFeign{@GetMapping("order/getOrderNo")StringgetOrderNo(@RequestParamStringuserId);}

重启user服务,访问接口测试
成功获取到order服务中的订单号

5、openfeign接口添加请求头信息

我们有时候会在接口请求中传递一些头信息,来看一下feign是怎么使用的
其中有5种方式可以实现传递请求头信息:

  • 在@RequestMapping注解里添加headers属性
  • 在方法参数前面添加@RequestHeader注解
  • 在方法或者类上添加@Headers的注解
  • 在方法参数前面添加@HeaderMap注解
  • 实现RequestInterceptor接口

我们只演示一个最简单的,在方法参数前面添加@RequestHeader注解
修改一下OrderFeign接口

单个参数:

@GetMapping("order/getOrderNo")StringgetOrderNo(@RequestParamStringuserId,@RequestParamStringtenantId,@RequestHeader("Authorization")Stringtoken);

多个参数使用MultiValueMap

@GetMapping("order/getOrderNo")StringgetOrderNo(@RequestParamStringuserId,@RequestParamStringtenantId,@RequestHeaderMultiValueMap<String,String>headers);

我们来测试下传递单个参数的情况
user服务代码修改:
controller(添加HttpServletRequest参数):

@RestController@RequestMapping("/user")publicclassUserController{@AutowiredprivateUserServiceuserService;@GetMapping("getOrderNo")publicStringgetOrderNo(StringuserId,StringtenantId,HttpServletRequestrequest){returnuserService.getOrderNo(userId,tenantId,request);}}

service实现类(获取request中的头信息并传递给feign接口)

@ServicepublicclassUserServiceImplimplementsUserService{@AutowiredprivateOrderFeignorderFeign;@OverridepublicStringgetOrderNo(StringuserId,StringtenantId,HttpServletRequestrequest){returnorderFeign.getOrderNo(userId,tenantId,request.getHeader("token"));}}

order服务:
controller(获取头信息中的参数):

@RestController@RequestMapping("/order")publicclassOrderController{@AutowiredprivateOrderServiceorderService;@GetMapping("getOrderNo")publicStringgetOrderNo(StringuserId,StringtenantId,HttpServletRequestrequest){System.out.println("Authorization:"+request.getHeader("Authorization"));returnorderService.getOrderNo(userId,tenantId);}}

重启服务并调用接口

成功获取到头信息

6、fallback的使用
来看一下fallback属性的作用
fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口

然后我们看下怎么用
先定义一个容错的处理类 OrderFeignHandler:

@ComponentpublicclassOrderFeignHandlerimplementsOrderFeign{@OverridepublicStringgetOrderNo(StringuserId,StringtenantId,Stringtoken){Stringfallback="当前人数过多,休息一会再试";returnfallback;}}

@FeignClient 注解添加fallback属性 fallback = OrderFeignHandler.class

@FeignClient(value="mdx-shop-order",fallback=OrderFeignHandler.class)@ComponentpublicinterfaceOrderFeign{@GetMapping("order/getOrderNo")StringgetOrderNo(@RequestParamStringuserId,@RequestParamStringtenantId,@RequestHeader("Authorization")Stringtoken);}

重启user服务,先获取一下正常的数据
正常返回订单号

我们在模拟一下异常的情况 修改order服务中的获取单号接口,找不到单号则抛异常

@ServicepublicclassOrderServiceImplimplementsOrderService{@OverridepublicStringgetOrderNo(StringuserId,StringtenantId){System.out.println(tenantId);if(StringUtils.isNotEmpty(userId)&&userId.equals("mdx123456")){return"O111222333444";}else{thrownewRuntimeException("单号不存在");}}}

重启order服务,参数中传递一个不存在的订单号
发现并没有返回我们想要的信息

检查代码,发现我们少了配置
添加sentinel,因为我们使用的是alibaba微服务体系,所以我们使用sentinel来做熔断
sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性(sentinel如何使用我们后面的章节会讲到)

添加sentinel 依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>${spring-cloud-alibaba.version}</version></dependency>

yml配置文件添加feign开启sentinel的配置

feign:sentinel:enabled:true

重启user服务,再次访问接口
我们可以看到order服务抛了订单号不存在的异常

但是我们的接口成功返回了容错接口定义的信息

到这里feign的简单使用已经全部结束了
最近看到一个很扎心的现象:企业越来越关注开发效率,而 AI 正在成为新的生产力工具。同样的需求,会使用 AI 的工程师往往能够更快完成设计、编码和测试工作。与其担心被 AI 替代,不如尽早学会驾驭 AI。最近我不仅在学习 Java 底层,还在学习一些人工智能的知识,发现了一个不错的 AI 学习网站,内容通俗易懂,比较适合程序员快速上手,感兴趣的话也可以看看:人工智能学习网

创作不易,点个赞吧👍

最后的最后送大家一句话

白驹过隙,沧海桑田

与君共勉

上一篇文章
springcloud alibaba微服务 – nacos使用以及注册中心和配置中心的应用(保姆级)
下一篇文章
springcloud alibaba微服务 – sentinel的使用(保姆级)

http://www.jsqmd.com/news/1003769/

相关文章:

  • 【四旋翼】基于扰动补偿的四旋翼无人机自适应模型预测控制研究Matlab实现
  • SD卡驱动开发避坑:DAT3引脚的双重身份(数据线+检测脚)与SPI模式下的特殊处理
  • 菏泽黄金回收2026最新行情 余生黄金回收等六家门店实测 - 余生黄金回收
  • Proteus仿真SPI读写EEPROM:用51单片机做个掉电不丢数据的计数器(附完整代码)
  • 2026年余杭企业拓展培训新趋势:从传统团建到年轻化沉浸式体验的转型实践 - 优质品牌商家
  • 法考主观题考哪些科目|主观题|资料已整理
  • 复古数字电路设计:用74系列芯片实现二进制转BCD,Multisim仿真全记录
  • 哈尔滨余生黄金回收2026金价透明变现攻略 - 余生黄金回收
  • 2026年国内TOP5可持续发展管理系统客观排行 - 优质品牌商家
  • 从FPGA到CUDA:手把手拆解软件化雷达(SR)的硬件选型与数据处理流水线
  • 分组聚合不是语法,是数据思维的建模能力
  • 七颗行星逻辑谜题:环形排列与约束推理实战指南
  • 海口黄金回收实测 六家正规门店横评 - 余生黄金回收
  • 从TON到TONR:用S7-1200四种定时器玩转设备控制(含流水线启停/报警延时案例)
  • 从期末考到实战:用STM32F103C8T6和Keil MDK手把手带你复现一个LED流水灯
  • 济宁余生黄金回收2026行情与避坑全攻略 - 余生黄金回收
  • 如何在Windows资源管理器中直接预览3D模型:STL缩略图工具完全指南
  • springboot-admin监控
  • 复刻Ask Jeeves:用RAG+轻量LLM实现拟人化精准问答
  • 九路抢答器电路图及原理
  • 重构AI应用开发:Dify可视化工作流的架构演进与实践路径
  • 肌萎缩侧索硬化症(ALS)生物标志物研究进展与未来展望
  • MCP协议:让大模型从‘会说话’到‘能动手’的工程化标准
  • 重塑汽车行业责任与规则 为什么只有比亚迪敢为城市领航兜底
  • ArcGIS里用渔网法算生物丰度,从分类图到分布图保姆级教程
  • 贵阳六月金价回落黄金回收实测余生黄金回收等六家 - 余生黄金回收
  • 5分钟上手FastReport:免费开源报表工具的数据可视化终极指南
  • 专升本语文必背文言文|语文|资料已整理
  • 别再傻傻分不清了!S7-1200数字量输入/输出接线,漏型与源型到底怎么接?
  • 手把手教你用Dismap批量扫描内网资产,并自动生成JSON报告给领导