目录
- 代码示例
- 文件服务接口
- 调用方
- 注意点:
- 2021.3.16更新:发新的坑
- 坑点:
- 原因分析
- 部分异常及解决方案
- 异常一:[Method has too many Body parameters](https://blog.csdn.net/haishiyizhenfeng/article/details/80607003)
- 异常二:[@FeignClient注入找不到的异常](https://blog.csdn.net/qq_28165595/article/details/102328066)
- 异常三:[feign.FeignException$MethodNotAllowed: status 405](https://blog.csdn.net/qq_43371556/article/details/100548389)
- 其他问题
代码示例
/*** 用于上传文传* UploadFile包含fileName、fileDesc* 不加@RequestParam等同于@RequestParam(required = false)* * @param file 文件* @param entity 文件的描述* @return*/@PostMapping("/add")public Response<Object> add(@RequestPart(value = "file") MultipartFile file,UploadFile entity,) {Response<Object> res = new Response<>();FileHandlerResult handlerResult = service.saveFile(file);return res;}
@FeignClient(value = "file-server")
public interface FileService {@PostMapping(value = "/static/add", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)Response<LinkedHashMap<Object, Object>> saveFile(@RequestPart(value = "file") MultipartFile file,@RequestParam(value = "fileName")String fileName,@RequestParam(value = "fileDesc")String fileDesc);
}
注意点:
- 参数是文件类型的要用@RequestPart注解;
- 调用方需要设置ContentType为multipart/form-data
@PostMapping(value = "xxx", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
- 调用方的文件参数名必须与服务接口的文件参数名相同,示例中文件参数都为
@RequestPart(value = "file") MultipartFile file
,参数名不同会导致服务接口接收到的文件为NULL。
2021.3.16更新:发新的坑
坑点:
调用方在接受MultipartFile
参数,并传给服务方时必须保持MultipartFile
参数的参数名与服务方一致(即multipartFile.getName()
必须与服务方的@RequestPart(value = "xxx") MultipartFile file
的value值相同),否则服务方会找不到参数!!!
最近在补充原本的分布式项目时,发现在调用发Controller层接受文件参数后,使用OpenFeign调用文件上传服务,一直报错(没有接受到参数file):
Required request part 'file' is not present
报错时调用方Controller代码:
/*** @RequestParam(name)MultipartFile[] file* 中的name, 即参数名必须与调用方接口的参数名相同* 否则服务方会报错Required request part 'file' is not present*/@PostMapping("/upload")public Response<Object> upload(@RequestParam("image")MultipartFile image){Response<Object> res = new Response<>();List<Object> data = new LinkedList<>();//调用服务方的接口Response<LinkedHashMap<Object, Object>> response = fileService.saveFile(image);if(response.getCode()==400){//保存失败res.fail(response.getDesc());return res;}data.add(response);res.success(data);return res;}
服务方代码:
@PostMapping("/add")public Response<Object> add(@RequestPart(value = "file") MultipartFile file,UploadFile entity,) {Response<Object> res = new Response<>();FileHandlerResult handlerResult = service.saveFile(file);return res;}
此时服务方接受不到调用方传的文件参数。
原因分析
在调用方的Controller中参数为@RequestParam("image")MultipartFile image
输出image的文件名,可以发现输出为:image
与@RequestParam("image")
的参数名一致
//输出结果image
System.out.println(image.getName());
而服务方接口需要的文件名 @RequestPart(value = "file") MultipartFile file
,即参数名字需要为file
,而openfeign传给服务方的文件参数名为image
,因此参数传递失败。
由此可知调用方在接受MultipartFile
参数,并传给服务方时必须保持MultipartFile
参数的参数名与服务方一致,否则会找不到参数!!!
部分异常及解决方案
异常一:Method has too many Body parameters
@GetMapping(value="/test")
Model test(String arg1, String arg1);
异常原因:
- 当使用Feign时,如果发送的是get请求,那么需要在请求的所有参数前加上@RequestParam注解修饰
- @RequestParam是用来修饰参数,不能用来修饰整个对象。
注意:使用@RequestParam修饰参数,请求默认的Content-Type 为 application/x-www-form-urlencoded
@RequestBody用来修饰对象
- Feign中可以有多个@RequestParam,但只能有不超过一个@RequestBody
- 既有@RequestBody也有@RequestParam,那么参数就要放在请求的url中,@RequestBody修饰的就要放在提交对象中。
示例:
public int save(@RequestBody Person p, @RequestParam("userId") String userId);
注意:使用@RequestBody修饰参数,请求的默认Content-Type 为 application/json 或 application/xml
异常二:@FeignClient注入找不到的异常
异常原因:
可能为启动类没有标注@EnableFeignClients
Springcloud中的服务间调用是通过Feign进行调用的,在调用方服务中,我们需要定义一些带有@FeignClient注解的接口类。并且在启动类上加上@EnableFeignClients注解。程序启动的时候,会检查是否有@EnableFeignClients注解,如果有该注解,则开启包扫描,扫描带有@FeignClient注解的接口。
异常三:feign.FeignException$MethodNotAllowed: status 405
异常原因:
调用方的方法参数没有标注@RequestParam
或参数名与服务接口的参数名不相同
其他问题
- 若是服务接口接受到的文件一直为NULL,请检测调用方法的文件参数名是否与服务接口文件参数名
- Feign部分版本好像不支持传文件的同时传文件的参数(Hoxton.SR1没有这个问题)