最近在做项目的时候,使用到了微服务架构,虽然之前接触过Dubbo这个阿里巴巴的微服务框架,但是上手K8S之后发现,这个框架真的挺难的,东西很多,下面给大家讲解一下在微服务调用过程中,传递图片文件遇到的问题。
一、问题代码
@FeignClient(value = "UploadFile",fallback = UploadFile.class)
public interface UploadFileService {
@PostMapping(value = "uploadFile", consumes = MediaType.APPLICATION_JSON_VALUE)
xxxVo uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("id") String id);
}
上面的代码是为了实现前端传递图片(MultipartFile类型)到后台,然后后台模块再进行服务模块间的调用,将传进来的图片通过 @FeignClient 服务调用传递到另外一个服务模块,但是在调用过程中出现以下问题。
二、问题描述
2.1 第一个异常
Caused by: java.lang.IllegalStateException: Method has too many Body parameters: public abstract
2.2第一个异常
Caused by: org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
通过查询网上的资料可以知道,大部分人的解决办法都是以下几种:
(1)GET方式
若是发送的是get请求,则需要在发送的请求参数前加上 @RequestParam 注解修饰,不过 @RequestParam 注解是用来修饰参数的,不能用来修饰整个对象,@RequestParam 注解还可以修饰多个。
(2)POST方式
若是发送的是post请求,则对修饰方法的注解有着要求,只能有且仅有存在一个 @RequestBody 注解修饰方法, @RequestParam 还是可以有多个,但需要注意:用 @RequestBody 修饰对象的话,如果 @RequestParam 和 @RequestBody 同时修饰,则参数就要放在请求的路径URL上面, @RequestBody 修饰的就要放在提交对象上。
三、问题解决
上面的两个解决办法,对我来说都没用,根本不起效果,最后通过俺的不懈努力,终于在知乎上找到一位大佬的博客,能够完美的解决上面两个错误。
3.1 指定请求提交内容
从 @PostMapping 中可知,consumes 参数是用来指定处理请求的提交内容类型的(Content-Type),我们一开始使用的
APPLICATION_JSON_VALUE 是(application/json)格式,接收文件的请求头格式应该为 MULTIPART_FORM_DATA_VALUE
(multipart/form-data)这种专门用于接收文件的格式才行,所以只需要更换了下面的配置,第一个异常就会消失,进而演变成第二个异常。
3.2 @RequestPart
从大佬的博客里面可以知道,出现第二个异常是因为使用 @RequestParam 注解的原因,当请求参数类型不再是 String 类型的时候, @RequestParam 是依赖于注册 Converter 或者 PropertyEditor 来解析参数。而 @RequestPart 则是通过 HttpMessageConverter 来根据 Content-Type 决定采用的消息转换器。
故只需要将修饰 MultipartFile 对象的 @RequestParam 注解换成 @RequestPart 便能正常运行。修改后代码如下:
@FeignClient(value = "UploadFile",fallback = UploadFile.class)
public interface UploadFileService {
@PostMapping(value = "uploadFile", produces = {MediaType.APPLICATION_JSON_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
xxxVo uploadFile(@RequestPart("file") MultipartFile file, @RequestParam("id") String id);
}