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

《OpenFeign 最佳实践:三大优雅调用远程服务的方式》​

1.RestTemplate存在的问题

观察一下我们远程调用的代码

虽说RestTemplate对HTTP封装后,已经比直接使用HTTPClient简单放便很多了,但是还是存在一些问题:

1.需要拼接url,虽然灵活性高,但是封装臃肿,url复杂时,容易出错。

2.代码可读性差,风格不统一 

这些问题,我们都可以通过OpenFeign来解决

2.OpenFeign介绍

OpenFeign是一个声明式的Web Service客户端,它让微服务间的调用更为简单,类似与controller调用service接口,只需要创建一个接口,然后让服务调用方添加注解即可使用OpenFeign 

OpenFeign的前身 

可以简单理解为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 

3.OpenFeign的快速上手 

注意:这里的快速上手是基于前面的nacos服务的代码 

1.引入依赖

在服务调用方的pom文件中引入下面的依赖,由于我的是订单服务调用产品服务,所以订单服务是服务调用方,所以在订单服务中引入下面的依赖 

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

2.添加注解 

在订单服务中的启动类中添加@EnableFeignClients,开启OpenFeign的功能,如下图

3.编写OpenFeign的客户端 

基于SpringMVC的注解来声明远程调用的信息,这个注解就是@FeignClient,我们单独将OpenFeign的客户端作为一个接口抽出来,如下图

 代码如下

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

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

1.name/value:指定FeignClient客户端从Nacos注册中心调用的微服务名称(),该属性用来服务发现

2.path:为FeignCient客户端的所有接口方法添加一个公共的前缀路径,避免在每一个方法上重复编写相同的路径

4.修改远程调用代码

修改远程调用的方法

@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate ProductApi productApi;public OrderInfo selectByOrderId(Integer id){OrderInfo orderInfo = orderMapper.selectByOrderId(id);ProductInfo productInfo=productApi.selectByProductId(orderInfo.getProductId());orderInfo.setProductInfo(productInfo);return orderInfo;}}

前后代码对比

5.测试接口

启动服务,远程调用接口,发现服务调用成功 

 可以看出来,使用Feign也可是实现远程调用,并且Feign简化了与HTTP服务交互的的过程,把REST客户端的定义转换为Java接口,并通过注解的方式来声明请求参数,请求方式等信息,使远程调用更加方便和间接

4.OpenFeign参数传递

1.传递单个参数

服务提供方product-service

@Slf4j
@RequestMapping("/product")
@RestController
public class ProductController implements ProductInterface {@Autowiredprivate ProductService productService;@RequestMapping("/p1")public String p1(Integer id){return "product-service接收参数:"+id;}
}

Feign客户端:

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

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

服务消费方orders-service:

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

测试接口: 发现成功调用服务

 

2.传递多个参数 

服务提供方product-service

 Feign客户端:

注意:@RequestParam注解不能省略  

服务消费方:orders-service服务的FeignController

测试接口:服务成功调用

3.传递对象

服务提供方product-service:

Feign客户端:ProductApi:

Feign在接收对象类型的参数时,要在前面加一个@SpringQueryMap注解 

服务消费方: orders-service服务的FeignController

测试接口: 成功调用远程服务

4.传递JSON数据 

服务提供方:product-service 

Feign客户端:ProductApi:

服务消费方:orders-service服务的FeignController

测试接口:远程调用服务成功

调用关系图,如下

5.Feign的最佳实践 

我们发现Feign中的方法声明和ProductController中的代码及其相似,其实是有两种方式去优化这写重复的部分的

5.1Feign继承式 

Feign支持继承的方式,我们可以将一些常见的操作封装到接口中,让服务提供方product-service去实现接口中声明的方法,让服务消费方的Feign直接继承这个接口即可

1.首先创建一个子工程---product-api

在ProductInterface的pom文件中引入下面的依赖,如下图

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

2.编写接口

创建一个ProductInterface接口 

如下图

由于我们将ProductInfo也复制到ProductInteface工程中了,此时将orders-service和product-service的ProductInfo类给注释掉了,因为ProductInfo是重复的代码,我们将其放在ProductInteface工程中就行了,如果想要在orders-service和product-service使用ProductInteface工程中的ProductInfo,由于是不同的过程,所以我们要将ProductInteface工程打包,将ProductInteface工程的jar包存储到我们本地的Maven仓库中,后续想使用ProductInteface工程中的ProductInfo,只需注入依赖即可

出现下面这部分就代表打包成功了 

3.服务提供方代码编写  

此时product-service的pom文件就会多出下面一部分依赖,这部分依赖就是ProductInteface工程的jar包的依赖,如下图

4.Feign客户端编写

此时发现Feign客户端中就省略了方法的声明 

5.服务消费方编写

此时需要注意的是由于此时使用的是ProductInterface里面的ProductInfo类,此时要重新导入ProductInfo的包,不然会报错 

没啥大变化,不过就是使用ProductInfo要重新导包

5.测试接口

服务调用成功 

5.2Feign抽取方式 

抽取的做法其实和继承的操作很相似,但是理念不同,抽取是直接将Feign的客户端也作为一个独立的模块,打成一个Jar包,后面服务的消费方只需要依赖该Jar即可。

简单来说,抽取就是直接创建一个子工程,在该子工程中直接完成Feign客户端的编写,后面服务消费方向使用工程中的Feign的客户端时,引入工程的jar包依赖就行了 

1.创建一个工程---product-api

先在product-api工程中引入下面的依赖:

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

然后直接在该工程中完成Feign客户端的编写,如下图 

然后将该工程打包,保存在本地的Maven仓库中

2.Product-service服务的修改

1.引入product-api工程jar包的依赖 

2.删除ProductApi和ProductInfo,统一使用product-api工程中的ProductApi和ProductInfo,此时还要将ProductApi和ProductInfo的路径修改为product-api的路径

3.orders-service服务的修改 

1.还是需要引入product-api工程jar包的依赖  

2.只需在启动类中指定需要加载的Feign客户端即可,如下图

4.测试接口

发现服务调用成功 

相关文章:

  • mysql explain使用
  • 基于springboot的校园商铺管理系统的设计与实现
  • HikariCP连接池使用和源码分析
  • NB-IoT NPUSCH(三)-资源映射
  • 一种C# 的SM4 的 加解密的实现,一般用于医疗或者支付
  • 多线程(1)
  • ODSA架构与操作-1
  • 2025最新Gemini 2.5 Pro API限制全面解析:最完整的使用指南与优化方案
  • 做好测试用例设计工作的关键是什么?
  • 仓颉入门:特性
  • 嵌入式自学第二十九天(5.27)
  • DFS入门刷题c++
  • AI 智能体的那些事—架构设计关键点
  • 数据库管理与高可用-MySQL数据库初体验
  • Java 内存模型与 volatile 关键字深度解析:从可见性到指令重排
  • 【键盘说明书备份】ENERGYFORT
  • 什么是舵机,如何控制舵机
  • LVGL(Grid)
  • 用Qt/C++玩转观察者模式:一个会聊天的设计模式
  • Baklib企业CMS实现内容智能归档与精准检索
  • 在国外做盗版电影网站吗/企业seo关键词优化
  • 怎么让网站排名下降/5000人朋友圈推广多少钱
  • 句容市住房和城乡建设局网站/关键词在线听免费
  • 怎么样做网站管理员/关键词排名怎么做好
  • 番禺网站建设服务/百度招聘
  • 金坛网站建设公司/软文写作网站