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

    @Bean
    public 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 {

    @Bean
    public Encoder feignEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
        // 将 Spring 的 HttpMessageConverters 适配为 Feign 的 Encoder
        Encoder springEncoder = new SpringEncoder(messageConverters);
        // 包装成支持表单编码的 Encoder
        return 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】✈️本地集成支付宝支付功能

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

先锋 Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值