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

OpenFeign-远程调用

RestTemplate存在的问题

观察之前写的远程调用的代码:

public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);String url = "<http://product-service/product/>" + orderInfo.getProductId();log.info("调用的url为:{}",url);ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}

虽说RestTemplate 对HTTP封装后, 已经⽐直接使⽤HTTPClient简单⽅便很多, 但是还存在⼀些问题:

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

微服务之间的通信⽅式, 通常有两种: RPC 和 HTTP.

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

  • RestTemplate
  • OpenFeign

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

常⻅的RPC框架有:

  1. Dubbo: https://cn.dubbo.apache.org/zh-cn/
  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的⼀个更强⼤更灵活的实现

<aside> 💡

我们现在⽹络上看到的⽂章, 或者公司使⽤的Feign, ⼤多都是OpenFeign.

本课程后续讲的Feign, 指的是OpenFeign

</aside>

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 官⽅⽂档:https://github.com/OpenFeign/feign

Spring Cloud Feign⽂档:Spring Cloud OpenFeign

OpenFeign快速上⼿

1.引入依赖(order-service)

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

2.通过注解,开启Feign的功能

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

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

3.编写客户端

在order-service下创建一个api目录:

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

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

@FeignClient 注解作⽤在接⼝上, 参数说明:

  • name/value:指定FeignClient的名称, 也就是微服务的名称, ⽤于服务发现, Feign底层会使⽤

    Spring Cloud LoadBalance进⾏负载均衡. 也可以使⽤ url 属性指定⼀个具体的url.

  • path: 定义当前FeignClient的统⼀前缀

4.修改远程调用

修改远程调⽤的⽅法

@Autowiredprivate ProductApi productApi;public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);/*String url = "<http://product-service/product/>" + orderInfo.getProductId();log.info("调用的url为:{}",url);ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);*/ProductInfo productInfo = productApi.getProductInfo(orderInfo.getProductId());orderInfo.setProductInfo(productInfo);return orderInfo;}

5.测试

启动服务, 访问接⼝, 测试远程调⽤:127.0.0.1:8080/order/1

可以看出来, 使⽤Feign也可以实现远程调⽤.

Feign 简化了与HTTP服务交互的过程, 把REST客⼾端的定义转换为Java接⼝, 并通过注解的⽅式来声

明请求参数,请求⽅式等信息, 使远程调⽤更加⽅便和间接.

OpenFeign参数传递

上面演示了Feign从url中获取参数,既然是会传递参数,那参数的类型就会有很多,接下来演⽰下Feign参数传递的其他⽅式。

传递单个参数

  1. 服务端需要提供相应的接口(product-service 的controller)

    @RestController
    @RequestMapping("/product")
    public class ProductController {@Autowiredprivate ProductService productService;@RequestMapping("/p1")public String p1(Integer id){return "product-service 接收到的参数,id" + id;}
    }
    
  2. Feign客户端声明

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

    <aside> 💡

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

    </aside>

  3. 服务消费⽅order-service

    @RestController
    @RequestMapping("/feign")
    public class FeignController {@Autowiredprivate ProductApi productApi;@RequestMapping("/o1")public String o1(Integer id){System.out.println("参数o1="+ id);return productApi.p1(id);}
    }
    
  4. 测试远程调用:127.0.0.1:8080/feign/o1?id=23

传递多个参数

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

  1. 服务提供⽅ product-service

    
    @RestController
    @RequestMapping("/product")
    public class ProductController {@Autowiredprivate ProductService productService;@RequestMapping("/p2")public String p2(Integer id,String name){return "product-service 接收到的参数,id=" + id + "name = " + name;}
    }
    
  2. Feign客户端声明

    @FeignClient(value = "product-service" , path = "/product")
    public interface ProductApi {@RequestMapping("/p2")String p2(@RequestParam("id") Integer id,@RequestParam("name") String name);
    }
    
  3. 服务消费⽅order-service

    @RestController
    @RequestMapping("/feign")
    public class FeignController {@Autowiredprivate ProductApi productApi;@RequestMapping("/o2")public String o2(@RequestParam("id")Integer id, @RequestParam("name")String name){return productApi.p2(id,name);}}
    
  4. 测试远程调用:127.0.0.1:8080/feign/o2?id=23&name=zhangsan

传递对象(模拟)

  1. 服务提供⽅ product-service

    		@RequestMapping("/p3")public String p3(ProductInfo productInfo){return "product-service 接收到的参数 productInfo =  " + productInfo.toString();}
    
  2. Feign客户端声明

        @RequestMapping("/p3")String p3(@SpringQueryMap ProductInfo productInfo);
    
  3. 服务消费⽅order-service

        @RequestMapping("/o3")public String o3(){ProductInfo productInfo = new ProductInfo();productInfo.setId(23);productInfo.setProductName("衣服");return productApi.p3(productInfo);}
    
  4. 测试远程调用:127.0.0.1:8080/feign/o3

传递JSON(模拟)

  1. 服务提供⽅ product-service

        @RequestMapping("/p4")public String p4(@RequestBody ProductInfo productInfo){return  "product-service 接收到的参数 productInfo =  " + productInfo.toString();}
    
  2. Feign客户端声明

        @RequestMapping("/p4")String p4(@RequestBody ProductInfo productInfo);
    
  3. 服务消费⽅order-service

        @RequestMapping("/o4")public String o4(){ProductInfo productInfo = new ProductInfo();productInfo.setId(23);productInfo.setProductName("衣服");return productApi.p4(productInfo);}
  4. 测试远程调用:127.0.0.1:8080/feign/o4

http://www.xdnf.cn/news/1192771.html

相关文章:

  • 计算机中的数据表示
  • Windows Server系统安装JDK,一直卡在“应用程序正在为首次使用作准备,请稍候”
  • Java程序员学从0学AI(六)
  • 框架式3D打印机结构设计cad【9张】三维图+设计说明书
  • openmv特征点检测
  • 如何使用Anaconda(miniconda)和Pycharm
  • Java 大视界 -- Java 大数据在智能安防视频监控系统中的视频语义理解与智能检索进阶(365)
  • x86汇编语言入门基础(三)汇编指令篇5 串操作
  • Windows11下和Vmware中的Ubuntu22.04设置samba服务遇到的一个问题- valid users和guest设置冲突
  • 零基础学习性能测试第三章:jmeter构建性能业务场景
  • java网络请求工具类HttpUtils
  • 智慧水库管理系统中标签工厂的建立方案
  • HTTP 协议的基本格式和 fiddler 的用法
  • PHP语法高级篇(六):面向对象编程
  • 可调谐激光器原理与设计 【DFB 与 DBR 激光器剖析】
  • 详解力扣高频SQL50题之1141. 查询近30天活跃用户数【简单】
  • 【区块链安全】DeFi协议安全漏洞深度分析:从闪电贷攻击到MEV套利
  • Nuxt 4:前端开发的全新篇章
  • java集合框架面试点(2)
  • 【C语言进阶】程序环境和预处理
  • 各种前端框架界面
  • HighlightingSystem
  • 精密全波整流电路(四)
  • Linux 如何统计系统上各个用户登录(或者登出)记录出现的次数?
  • python 检测蜂窝网络,实现掉网自动拨号
  • 自定义定时任务功能详解
  • SGLang 核心技术详解
  • GO 从入门到精通2
  • TCP如何解决网络切换问题
  • 简单实现支付密码的页面及输入效果