【openfeign】OpenFeign的使用、GET请求和POST请求

news2024/9/28 7:17:37

RPC全称是Remote Procedure Call,即远程过程调用,其对应的是我们的本地调用。

RPC的目的是:让我们调用远程方法像调用本地方法一样。

//本地调用
R result = orderService.findOrderByUserId(id);
//RPC远程调用  orderService为代理对象
R result = orderService.findOrderByUserId(id);

RPC框架设计架构:

那么微服务之间如何方便优雅的实现服务间的远程调用?

什么是Feign

Feign是Netflix开发的声明式、模板化的HTTP客户端,Feign可帮助我们更加便捷、优雅地调用HTTP API。

Feign可以做到使用HTTP请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP请求。它像Dubbo一样,consumer直接调用接口方法调用provider,而不需要通过常规的Http Client构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Eureka,从而使得Feign的使用更加方便。

Feign的设计架构:

Spring Cloud Alibaba快速整合Feign

引入依赖

<!-- openfeign 远程调用 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

编写调用接口+@FeignClient注解

package com.morris.user.client;

import com.morris.user.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@FeignClient(value = "order-service", path = "/order")
public interface OrderClient {

    @GetMapping("findOrderByUserId")
    List<Order> findOrderByUserId(@RequestParam("userId") Long userId);

}

调用端在启动类上添加@EnableFeignClients注解

package com.morris.user;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients // 开启OpenFeign
@SpringBootApplication
public class UserServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }

}

发起调用,像调用本地方式一样调用远程服务

package com.morris.user.controller;

import com.morris.user.client.OrderClient;
import com.morris.user.entity.Order;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("user3")
public class OpenFeignController {

    @Resource
    private OrderClient orderClient;

    @GetMapping("findOrderByUserId1")
    public List<Order> findOrderByUserId1(Long userId) {
        return orderClient.findOrderByUserId(userId);
    }

}

Feign的继承特性可以让服务的接口定义单独抽出来,作为公共的依赖,以方便使用。

GET请求

没有参数

没有参数就很简单,只需要使用@GetMapping标识好请求路径就可以了。

@GetMapping("getOrder")
Order getOrder();

多个基础类型参数

Get请求多个参数时,需要使用@RequestParam或者@PathVariable注解,这是因为在加载方法元数据的时候,如果该形参没有注解,默认会直接将其放在请求体中,这样GET请求时就会报错。

而且注解中的value属性必须指定绑定的参数名,不然会报错RequestParam.value() was empty on parameter 0

@GetMapping("findOrderByUserId")
List<Order> findOrderByUserId(@RequestParam("userId") Long userId);

@GetMapping("findOrderByUserId/{userId}")
List<Order> findOrderByUserId2(@PathVariable("userId") Long userId);

集合数据参数

使用GET请求传递集合参数时,需要这么写:

    @GetMapping("getOrders")
    List<Order> getOrders(@RequestParam("idList") List<Long> idList);

在请求时,URL集合值使用逗号隔开:

http://localhost:8030/user3/getOrders=1,2

在使用Feign调用时,可以从日志看到,Feign自动将集合类型的参数进行了解析拼接。

2023-08-14 16:07:23.283 DEBUG 20288 --- [nio-8030-exec-6] com.morris.user.client.OrderClient       : [OrderClient#getOrders] ---> GET http://order-service/order/getOrders?idList=1&idList=2 HTTP/1.1

单个对象参数

当Get请求参数超过三个时,就需要进行查询参数封装为对象。

上面说到当参数没有注解时,就会放入到请求体中,但是@RequestParam不支持直接传递对象类,这时就需要使用@SpringQueryMap注解,它可以将对象属性及值,转为键值对拼接在URL后面。

@GetMapping("checkOrder")
Order checkOrder(@SpringQueryMap Order order);

从日志中可以看出对象被转为键值对拼接在URL后面:

2023-08-14 16:10:05.108 DEBUG 20288 --- [nio-8030-exec-9] com.morris.user.client.OrderClient       : [OrderClient#checkOrder] ---> GET http://order-service/order/checkOrder?goodName=Iphone%2013&price=9999&id=1&userId=1 HTTP/1.1

多个对象参数(不支持)

多个对象参数时,只需要使用多个@SpringQueryMap即可:

@GetMapping("getOrderUser")
Order getOrderUser(@SpringQueryMap Order order, @SpringQueryMap User user);

从日志中可以看出第二个对象不会被转为键值对拼接在URL后面:

2023-08-14 16:21:09.061 DEBUG 24776 --- [nio-8030-exec-3] com.morris.user.client.OrderClient       : [OrderClient#getOrderUser] ---> GET http://order-service/order/getOrderUser?goodName=Iphone%2013&price=9999&id=1&userId=1 HTTP/1.1

一个对象+基础类型参数

需要注意实体类中的属性和这个基础类型参数名不能相同,不然拼接到URL中,两个同名参数传递过去就会覆盖了。

@GetMapping("getOrderName")
Order getOrderName(@SpringQueryMap Order order, @RequestParam("name") String name);

下载文件

下载文件需要注意的是,应该返回二进制数据,还有GET请求时,需要对URL进行编码,不然会报错编码不符合规范,其他没什么区别。

@GetMapping("/download")
byte[] download(@RequestParam("filePath") String filePath);

POST请求

POST请求也支持将参数放在URL上,使用方式与GET请求类似。

传递单个对象参数

服务消费者的参数不需要增加任何注解,就会放入到请求体中,这个时候会使用编码器,将对象编码,并以Content-Type: application/json形式发送请求。

@PostMapping("saveOrder")
Long saveOrder(Order order);

所以只要注意在服务提供者中,添加@RequestBody注解,将请求体转为对象即可。

传递多个对象参数(不支持)

如果像下面这样使用两个@RequestBody,消费者启动时是会报错的:

@PostMapping("saveOrderAndUser")
Long saveOrderAndUser(Order order, User user);

报错日志如下:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.morris.user.client.OrderClient': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Method has too many Body parameters: public abstract java.lang.Long com.morris.user.client.OrderClient.saveOrderAndUser(com.morris.user.entity.Order,com.morris.user.entity.User)
Warnings:

这时候需要将两个对象封装在一个对象中,变成单个对象进行请求传递。

上传文件

上传文件时,需要注意的是需要使用@RequestPart注解,Fiegn会解析这个注解,标记为上传文件请求,还需要指定consumes为MULTIPART_FORM_DATA_VALUE,编码器会根据这个配置,将文件对象进行编码。

@PostMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String upload(@RequestPart("file") MultipartFile file);

在调用方,上传文件时,则需要将文件对象转为MultipartFile。

@GetMapping("upload")
public String upload() throws URISyntaxException {
    File file = new File(OpenFeignController.class.getResource("/application.yml").toURI());
    MultipartFile multipartFile =fileToMultipartFile(file);
    return orderClient.upload(multipartFile);
}

private MultipartFile fileToMultipartFile(File file) {
    String fieldName = "file";
    FileItemFactory factory = new DiskFileItemFactory(16, null);
    FileItem item = factory.createItem(fieldName, "multipart/form-data", true, file.getName());
    int bytesRead = 0;
    byte[] buffer = new byte[8192];
    try {
        FileInputStream fis = new FileInputStream(file);
        OutputStream os = item.getOutputStream();
        while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
            os.write(buffer, 0, bytesRead);
        }
        os.close();
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return new CommonsMultipartFile(item);
}

一般不采用Feign去上传文件,这种方式请求链路比较长,性能很低,一般都是前端直接上传到文件服务器,然后再告诉后台上传了哪个文件。

header中加参数

有时候接口验签的场景header中需要追加一些参数,可以通过@RequestHeader注解实现。

@GetMapping("header1")
String header1(@RequestHeader(name = "authorization")String authorization);

如果是固定参数,可以通过@Headers指定:

@PostMapping("header2")
@Headers({"Content-Type:application/json","Authorization:{authorization}"})
String header2(@RequestHeader(name = "authorization")String authorization, User user);

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

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

相关文章

蓝牙Mesh设备配网过程及抓包分析

配网过程 说明Mesh消息类型配网过程 信标阶段(Beaconing)Unprovisioned Device beaconLink Open/Link ACK/Link CloseLink OpenLink ACKLink Close 邀请阶段(Invitation)Provisioning InviteProvisioning Capabilities 交换公钥阶段(Exchanging public keys)Provisioning Start…

Oracle数据库经纬度坐标查询优化与结果错误原因分析、SQL中WKT超长文本字符串处理

文章目录 一、Oracle几何空间数据对象和其他数据库的差异二、Oracle查询一个经纬度坐标是否在边界内部2.1 查询条件2.2 查询结果错误&#xff0c;似乎是仅做了MBR匹配2.3 错误原因2.4 解决办法 三、SQL中WKT超长文本在Oracle中如何编写3.1 Oracle中执行含超长文本的SQL报错3.2 …

健身耳机哪个牌子好?推荐几款最适合健身运动用的耳机牌子

对于健身爱好者来说&#xff0c;选择一款适合健身运动的耳机是至关重要的&#xff0c;无论你是跑步、举重还是瑜伽&#xff0c;有适合自己的耳机戴着听歌&#xff0c;能够让你更加投入、更加享受健身的过程。可现在如今的耳机品牌琳琅满目&#xff0c;在选择上自然是要花上不少…

搭建Everything+cpolar在线资料库,实现随时随地访问

Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问 文章目录 Everythingcpolar搭建在线资料库&#xff0c;实现随时随地访问前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 前…

山西电力市场日前价格预测【2023-08-22】

日前价格预测 预测明日&#xff08;2023-08-22&#xff09;山西电力市场全天平均日前电价为313.08元/MWh。其中&#xff0c;最高日前电价为354.58元/MWh&#xff0c;预计出现在18: 45。最低日前电价为271.10元/MWh&#xff0c;预计出现在12: 30。 价差方向预测 1&#xff1a; 实…

CrossOver2023虚拟机工具最新版本功能介绍

想要在Mac OS中运行Windows程序&#xff0c;除了使用虚拟机外&#xff0c;使用CrossOver在Mac OS系统中运行Windows程序是非常不错的选择。CrossOver基于Wine技术&#xff0c;可以在Mac OS上运行许多Windows应用程序&#xff0c;而无需安装整个Windows操作系统。 本次发布的Cr…

Paraverse平行云入选启元计划元宇宙TOP20榜单

近日&#xff0c;2023全球数字经济大会互联网3.0峰会上&#xff0c;由中关村大数据产业联盟、中国科协科技传播中心、北京信息化协会共同发起的启元计划发布其成果&#xff0c;同时公布启元计划TOP20以及TOP50企业入选名单。凭借技术与生态优势&#xff0c;「Paraverse平行云」…

docker 05(dockerfile)

一、docker镜像原理 镜像可以复用 二、容器转镜像 将容器保存为镜像[参考] docker commit -a -m 现有容器ID 保存后的名称&#xff1a;版本号 -a :提交的镜像作者&#xff1b; -c :使用Dockerfile指令来创建镜像&#xff1b; -m :提交时的说明文字&#xff1b; -p :…

常用字符串匹配算法

一、BF匹配 BF算法中的BF是Brute Force的缩写&#xff0c;中文叫作暴力匹配算法&#xff0c;也叫朴素匹配算法。 BF算法的时间复杂度很高&#xff0c;是O(nm)&#xff0c;但在实际的开发中&#xff0c;它却是一个比较常用的字符串匹配算法。 第一&#xff0c;实际的软件开发中…

网络安全(黑客)自学笔记建议

前言 1.不要试图以编程为基础的学习开始学习 我在之前的回答中&#xff0c;我都一再强调不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;而且实际向安全过渡后可用到的关键知识并不多 一般人如果想要把编程学好再开…

安防视频监控平台EasyCVR视频集中存储平台接入RTSP设备出现离线情况的问题解决方案

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

Web Worker的使用

Web Worker 前言一、Web Worker是什么&#xff1f;二、使用步骤2.1 创建 Web Worker2.2 监听消息2.3 发送消息 三、优点与缺点3.1 优点3.2 缺点 总结 前言 JavaScript采用的是单线程模型&#xff0c;也就是说&#xff0c;所有任务只能在一个线程上完成&#xff0c;一次只能做一…

【leetcode 力扣刷题】 两数/三数/四数之和 哈希表和双指针解题

两数/三数/四数之和 题目合集 哈希表求解1. 两数之和454. 四数相加Ⅱ 双指针求解15.三数之和18. 四数之和 这个博客是关于&#xff1a;找出数组中几个元素&#xff0c;使其之和等于题意给出的target 这一类题目的&#xff0c;但是各个题之间又有些差异&#xff0c;使得需要用不…

lwIP更新记10:IP 冲突检测

lwip-2.2.0-rc1 版本于 2023 年 6 月 29 日发布&#xff0c;带来了我期盼已久的 IPv4 冲突检测 功能。 lwip-2.2.0-rc1 版本重新回归了 master 分支&#xff08;主分支&#xff09;&#xff0c;不再使用单独的稳定分支。 master 分支 是一个 Git&#xff08;版本控制程序&…

C#8.0本质论第四章--操作符和控制流程

C#8.0本质论第四章–操作符和控制流程 4.1操作符 有些操作符以符号的形式出现&#xff0c;例如、-、?.或者??等&#xff0c;而另一些操作符则为关键词&#xff0c;例如default和is。 4.1.1一元正负操作符 一元正操作符()对值几乎没有影响&#xff0c;它在C#中是多余的。…

python 连接Redis 数据库

pip install redis python代码 import redis# 连接数据库 r redis.Redis(host192.168.56.15, port6379, db0)# 存储数据 #r.set(key, value) r.set(name, zaraNet)# 获取数据 value r.get(name) print(value)# 关闭连接&#xff08;可选&#xff09; r.close()

AP9196 DC-DC 升压 升降压 恒流电源管理芯 LED电源驱动IC

产品说明 AP9196 是一系列外围电路简洁的宽调光比升压调光恒流驱动器&#xff0c;适用于 3-40V 输入电压范围的 LED照明领域。AP9196 采用我司专利算法&#xff0c;可以实现高精度的恒流效果&#xff0c;输出电流恒流精度≤3&#xff05;&#xff0c;电压工作范围为5-40V&…

Redis 缓存满了怎么办?

引言 Redis 缓存使用内存来保存数据&#xff0c;随着需要缓存的数据量越来越大&#xff0c;有限的缓存空间不可避免地会被写满。此时&#xff0c;应该怎么办&#xff1f;本篇文章接下来就来聊聊缓存满了之后的数据淘汰机制。 值得注意的是&#xff0c;在 Redis 中 过期策略 和…

【rar密码】rar压缩包密码列表

之前给大家介绍过WinRAR自动加密的设置方法&#xff0c;今天再介绍一种RAR压缩包加密方法&#xff1a;整理密码。 什么是整理密码&#xff1a; 在加密rar文件的时候&#xff0c;点击下拉框选择密码&#xff0c;不用输入密码 设置方法&#xff1a; 前面的操作步骤和设置自动…

正中优配:尾盘拉升的股票第二天的走势?

尾盘拉升是指买卖日快结束时股票价格呈现上涨的状况。关于许多投资者来说&#xff0c;这一般是好事情&#xff0c;因为它可认为他们带来更高的收益。但是&#xff0c;人们常常会问尾盘拉升的股票第二天的走势怎么。本文将从多个角度进行剖析。 首要&#xff0c;咱们需求认识到这…