@RequestParam和@RequestPart区别及Feign踩坑

概述

在做视频文件上传时遇到的问题,参考FileUploadException: the request was rejected because no multipart boundary was found

@RequestParam

绝大多数人都知道RequestParam,看看源码:

/**
 * Annotation which indicates that a method parameter should be bound to a web
 * request parameter.
 *
 * <p>Supported for annotated handler methods in Spring MVC and Spring WebFlux
 * as follows:
 * <ul>
 * <li>In Spring MVC, "request parameters" map to query parameters, form data,
 * and parts in multipart requests. This is because the Servlet API combines
 * query parameters and form data into a single map called "parameters", and
 * that includes automatic parsing of the request body.
 * <li>In Spring WebFlux, "request parameters" map to query parameters only.
 * To work with all 3, query, form data, and multipart data, you can use data
 * binding to a command object annotated with {@link ModelAttribute}.
 * </ul>
 *
 * <p>If the method parameter type is {@link Map} and a request parameter name
 * is specified, then the request parameter value is converted to a {@link Map}
 * assuming an appropriate conversion strategy is available.
 *
 * <p>If the method parameter is {@link java.util.Map Map&lt;String, String&gt;} or
 * {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}
 * and a parameter name is not specified, then the map parameter is populated
 * with all request parameter names and values.
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
}

使用@RequestParam可以应付绝大多数场景(99.99%,4个9),这也是开发5年来并没注意到RequestPart的原因?

@RequestPart

今天第一次注意到这个注解:

/**
 * Annotation that can be used to associate the part of a "multipart/form-data" request
 * with a method argument.
 *
 * <p>Supported method argument types include MultipartFile in conjunction with
 * Spring's MultipartResolver abstraction, {@code javax.servlet.http.Part} in
 * conjunction with Servlet 3.0 multipart requests, or otherwise for any other method
 * argument, the content of the part is passed through an HttpMessageConverter
 * taking into consideration the 'Content-Type' header of the request part. This is
 * analogous to what @RequestBody does to resolve an argument based on the
 * content of a non-multipart regular request.
 *
 * <p>Note that @RequestParam annotation can also be used to associate the part
 * of a "multipart/form-data" request with a method argument supporting the same method
 * argument types. The main difference is that when the method argument is not a String
 * or raw MultipartFile / Part, {@code @RequestParam} relies on type
 * conversion via a registered Converter or PropertyEditor while
 * {@link RequestPart} relies on {@link HttpMessageConverter HttpMessageConverters}
 * taking into consideration the 'Content-Type' header of the request part.
 * {@link RequestParam} is likely to be used with name-value form fields while
 * {@link RequestPart} is likely to be used with parts containing more complex content
 * e.g. JSON, XML).
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestPart {
}

区别

Note that @RequestParam annotation can also be used to associate the part of a “multipart/form-data” request with a method argument supporting the same method argument types. The main difference is that when the method argument is not a String or raw MultipartFile / Part, @RequestParam relies on type conversion via a registered Converter or PropertyEditor while RequestPart relies on HttpMessageConverter HttpMessageConverters taking into consideration the ‘Content-Type’ header of the request part. @RequestParam is likely to be used with name-value form fields while @RequestPart is likely to be used with parts containing more complex content.

翻译:
注意到,@RequestParam注解还可以用于将multipart/form data请求的部分与支持相同方法参数类型的方法参数相关联。区别在于,当方法参数不是字符串或原始多部分文件/部分时,@RequestParam依赖于通过注册的转换器或PropertyEditor进行的类型转换,而RequestPart依赖于HttpMessageConverterHTTP消息转换器,同时考虑到请求部分的“Content type”头@RequestParam可能与name-value表单字段一起使用,而@RequestPart可能与包含更复杂内容的部分一起使用。

解释:
@RequestPart主要用来处理content-type为multipart/form-datamultipart/mixed stream发起的请求,可以获取请求中的参数,包括普通文本、文件或复杂对象比如JSON、XML等,针对复杂对象,需要明确对应的content-type。

@RequestParam默认主要来处理query parameters, form data,and parts in multipart requests, 且是 key-value键值对这种文本,要区分

Spring MVC:

会把query parameters, form data,and parts in multipart requests 里面的参数组合到一起存放在一个参数Map里(key相同的参数,值会追加)

Spring WebFlux:

只会处理query parameters

@RequestPart这个注解用在multipart/form-data表单提交请求的方法上。
2.支持的请求方法的方式MultipartFile,属于Spring的MultipartResolver类。这个请求是通过http协议传输的。
3.@RequestParam也同样支持multipart/form-data请求。
4.他们最大的不同是,当请求方法的请求参数类型不再是String类型的时候。
5.@RequestParam适用于name-valueString类型的请求域,@RequestPart适用于复杂的请求域(像JSON,XML)

1 @RequestParam适用于name-value表单字段,而@RequestPart经常被用于处理复杂内容(例如JSON, XML) 2 当方法的参数类型不是String或者原生的MultipartFile / Part,@RequstParam需要注册并使用 Converter or PropertyEditor 进行类型转换,而 RequestPart 可通过请求体中的“Content-Type“进行使用 HttpMessageConverters转换

RequestPart 注解会生成临时文件,而RequestParam 则不会生成临时文件,效率上 ReqeustParam 会比 RequestPart 快一个数量级

posted @ 2021-07-02 19:35  johnny233  阅读(502)  评论(0编辑  收藏  举报  来源