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

【Feign】⭐️使用 openFeign 时传递 MultipartFile 类型的参数参考

💥💥✈️✈️欢迎阅读本文章❤️❤️💥💥

🏆本篇文章阅读大约耗时三分钟

⛳️motto:不积跬步、无以千里

📋📋📋本文目录如下:🎁🎁🎁

目录

前言

模拟

解决方案(一)

解决方案(二)

章末

前言

        小伙伴们大家好,这篇文章主要描述下最近在开发时遇到的一个服务之间通过 openFeign 调用时遇到的参数传递问题,如题目所述,该参数类型正是 MultipartFile。

        在网上有很多解决方案,比如另外引入 feign + spring 的联合依赖(叫什么记不住了),或者转换成字节数组传递,接收方再转换为 MultipartFile 对象(要引入MockMultifile 依赖,应该是这个),然后还有本文使用的这种方案(不用引入依赖,改动也不多)

        先来模拟下大致的使用场景,也可以直接跳过模拟看解决方案(环境不同,也可能解决不了各位的问题,请谅解)

模拟

        本地模拟就以两个简单服务之间的调用实现,对应一个客户端,一个服务端,场景就是从客户端调用服务端的接口,中间需要传递 MultipartFile 类型的参数,要怎么成功把参数传递到服务端

        1、客户端会暴露一个接口,参数为 MultipartFile 类型的 file 参数,然后通过 feign 调用服务端的接口,feign 配置也很简单,指定了服务端地址和定义了一个方法

        2、服务端

        提供的方法很简单,打印 file 的大小,然后返回给客户端该参数的 大小+原始名称

        3、测试

        目前这种情况,在调用客户端暴露的接口,参数可以成功传到客户端,但是从客户端传到服务端的时候会遇到异常,服务端提示异常如下:

Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Current request is not a multipart request] with root cause

解决方案(一)

        (补充:该方法只适用于整个服务使用的 feign 传递参数时不会有 @RequestBody 类型的传递方式,有这种请求和 Multipartfile 类型请求的,可以再往下看)

        指定自定义编码器,并且标注请求头,使用 @RequestPart 注解标注参数。具体实现案例如下:

        1、编码配置类

import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author HuangBenben */
@Configuration
public class FeignConfig {@Beanpublic Encoder devEncoder() {return new SpringFormEncoder();  // 使用 SpringFormEncoder 实现 Encoder 接口}
}

        2、feign 接口指定编码和请求头以及参数注解

        @FeignClient 注解中指定 configuration 的值为 自己创建的编码配置类

        具体的方法定义加上对应请求头

        使用 @RequestPart 注解

        3.服务端调整

        服务端在接收参数时也使用 @RequestPart 注解

         4、测试

        可以正常传递参数并且接收到了服务端的返回值

 解决方案(二)

        首先很抱歉上面的解决方案没有调研仔细,会影响到下面这种情况

        昨儿查了许久找到的简单实现 MultipartFile 类型通过 feign 在服务间传递的方法,今儿发现有别的隐患,如果服务间也有 @Requestbody 类型的参数传递,在上面的解决方法基础上会报错,参数传递失败,场景模拟和解决方案如下:

        1、如下使用会有异常,当前服务有别的 feing 定义,并且使用 @RequestBody 注解,调用时客户端直接异常:

feign.codec.EncodeException: class org.example.entity.Email is not a type supported by this encoder.

        假设要传递这种请求体

        2、解决

        在原先自定义的 FeignConfig 基础上调整为以下代码,再次测试 @RequestBody , MultipartFile 类型 以及 @RequestParam 传递都没问题

        这样配置的话,前面的那种解决方法中要在 feign 中声明指定配置类的操作也不需要了

import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author HuangBenben*/
@Configuration
public class FeignConfig {@Beanpublic Encoder feignEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {// 将 Spring 的 HttpMessageConverters 适配为 Feign 的 EncoderEncoder springEncoder = new SpringEncoder(messageConverters);// 包装成支持表单编码的 Encoderreturn new SpringFormEncoder(springEncoder);}
}

        这种调整是因为 feign 的自动调整传递形式,详细解释如下:

        通过配置 SpringFormEncoder 包装 SpringEncoder,可以同时支持 @RequestBody 的 JSON 参数传递 和 multipartFile 文件上传,但需要满足以下条件

        1. 支持的场景
        参数类型                    编码方式                                触发条件
@RequestBody 对象         JSON(application/json)    方法声明中包含 @RequestBody,且未指定 consumes 类型
@RequestPart 文件           multipart/form-data               方法参数中包含 MultipartFile 类型,且声明 consumes = MediaType.MULTIPART_FORM_DATA_VALUE
        2. 自动选择编码的逻辑
        JSON 编码(SpringEncoder)
当方法参数标记为 @RequestBody 且未强制指定 consumes 类型时,Feign 会优先使用 SpringEncoder 中的 Jackson2JsonHttpMessageConverter 将对象序列化为 JSON。

        Multipart 编码(SpringFormEncoder)
当方法参数包含 MultipartFile 且声明 consumes = MediaType.MULTIPART_FORM_DATA_VALUE 时,SpringFormEncoder 会自动切换为 multipart/form-data 编码模式。

章末

        这里简易将使用到自定义编码配置类的 feign 接口统一放到一个调用类中,不要跟正常调用的方法放一起,这里指定了编码配置可能会影响别的方法

        文章到这里就结束了~

往期推荐 > > > 

 【接口负载】✈️整合 Resilience4j 指定接口负载,避免过载

 【SpringBoot】⭐️整合 Redis 实现百万级数据实时排序

 【SpringBoot】✈️本地集成支付宝支付功能

    


http://www.mrgr.cn/news/96684.html

相关文章:

  • SpringBoot详细教程(持续更新中...)
  • HCIP(RSTP+MSTP)
  • 记忆学习用内容
  • Sentinel[超详细讲解]-4
  • Axure疑难杂症:完美解决文本框读取、赋值、计数(玩转文本框)
  • 安卓一些接口使用
  • python文件的基本操作和文件读写
  • 实现在Unity3D中仿真汽车,而且还能使用ros2控制
  • Docker部署sprintboot后端项目
  • 【Golang】泛型与类型约束
  • 【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】【思路篇】A题解题全流程(持续更新)
  • 浏览器 ➔ 服务器or服务器 ➔ 浏览器:
  • linux进程信号 ─── linux第27课
  • Dubbo分布式框架学习(1)
  • (二)机器学习---常见任务及算法概述
  • jdk21使用Vosk实现语音文字转换,免费的语音识别
  • Laravel Trait 实现 统一JSON 响应格式
  • Spring-事务属性
  • Axure项目实战:智慧运输平台后台管理端-承运商管理(中继器筛选)
  • 博客学术汇测试报告