@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<String, String>} or
* {@link org.springframework.util.MultiValueMap MultiValueMap<String, String>}
* 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依赖于HttpMessageConverter
HTTP消息转换器,同时考虑到请求部分的“Content type”头@RequestParam可能与name-value表单字段一起使用,而@RequestPart可能与包含更复杂内容的部分一起使用。
解释:
@RequestPart主要用来处理content-type为multipart/form-data
或multipart/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 快一个数量级