FeignClient调用服务及上传文件的注意点及问题

目录

  • 代码示例
    • 文件服务接口
    • 调用方
  • 注意点:
  • 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
    );
}

注意点:

  1. 参数是文件类型的要用@RequestPart注解
  2. 调用方需要设置ContentType为multipart/form-data
@PostMapping(value = "xxx", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  1. 调用方的文件参数名必须与服务接口的文件参数名相同,示例中文件参数都为@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没有这个问题)

你可能感兴趣的:(springcloud,spring,java,springcloud,feign)