zl程序教程

您现在的位置是:首页 >  后端

当前栏目

浅析SpringMVC请求参数注解@RequestParam/@RequestBody传递FormData的问题

SpringMVC 参数 请求 注解 浅析 传递 问题 RequestBody
2023-09-11 14:19:55 时间

一、问题背景

  使用SpringMVC请求注解遇到的两个小问题:

1、如果用@requestBody注解,则请求体内容类型一般要为application/json,如果其类型为multipart/form-data,则会报错:不支持的媒体类型;

2、如果用@requestParam注解,默认必须要传该参数名对应的参数,否则会报错。

二、原因分析

1、@RequestParam 用来处理 Content-Type: 为 application/x-www-form-urlencoded编码的内容。(注意:Http协议中,如果不指定Content-Type,则默认传递的参数就是application/x-www-form-urlencoded类型)

  RequestParam可以接受简单类型的属性,也可以接受对象类型。 实质是将Request.getParameter() 中的Key-Value参数Map利用Spring的转化机制ConversionService配置,转化成参数接收对象或字段。

  TIPS:在Content-Type: application/x-www-form-urlencoded的请求中, get 方式中queryString的值,和post方式中 body data的值都会被Servlet接收到,并转化到Request.getParameter()参数集中,所以@RequestParam可以获取到值。

2、@RequestBody 处理 HttpEntity 实体类传递过来的数据,一般用来处理非 Content-Type: application/x-www-form-urlencoded 编码格式的数据。

(1)GET请求中,因为没有HttpEntity,所以@RequestBody并不适用。

(2)POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型 Content-Type(一般比如前端请求的库都自动设置了,很多如 axios 都很智能,你传 对象,就自动设置为 application/json;你传的是 FormData 格式,就自动设置为 application/x-www-form-urlencoded),SpringMVC通过使用HandlerAdapter 配置的HttpMessageConverters来解析HttpEntity中的数据,然后绑定到相应的bean上。

3、总结:

(1)在GET请求中,不能使用@RequestBody。

(2)在POST请求,可以使用@RequestBody和@RequestParam,但是如果使用@RequestBody,对于参数转化的配置必须统一。

三、解决

  所以在传 FormData 时,应该使用 @RequestParam 方式

public OperationInfo saveDBDoc(@RequestParam(required = false) Integer id,
                                @RequestParam String title,
                                @RequestParam(required = false, defaultValue = "PUBLIC") String encryptLevel,
                                @RequestParam(required = false) MultipartFile file,
                                @RequestParam(required = false) MultipartFile imageUrl,
                                @RequestParam(required = false) Boolean isRepeat) throws Exception {
    // ...
    DBDocVO docVO = DBDocVO.builder()
        .id(id)
        .title(title)
        .encryptLevel(encryptLevel)
        .isRepeat(isRepeat)
        .build();
    // ...
}