您的位置:首页 > 文旅 > 旅游 > @RequestPart 与 @RequestBody、@RequestParam 注解的异同点

@RequestPart 与 @RequestBody、@RequestParam 注解的异同点

2024/12/23 11:38:21 来源:https://blog.csdn.net/qq_38257958/article/details/140314267  浏览:    关键词:@RequestPart 与 @RequestBody、@RequestParam 注解的异同点

前言

@RequestPart 注解是我们在JavaEE 开发中,比较常见的一个注解。它经常会与 @RequestBody 、@RequestParam 注解进行比较,这篇博文我们以案例和源码相结合,分析这几个注解的异同点。

案例演示

创建实体类 User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {private String username;private String password;@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

@RequestPart vs @RequestBody

实体类User接收传参
@RequestBody 方式接口及响应
@RestController
@RequestMapping("/compare")
public class CompareController {@PostMapping("/body_entity")public String bodyEntity(@RequestBody User user) {return user.toString();}}

@RequestPart 方式接口及响应
@PostMapping("/part_entity")
public String partEntity(@RequestPart("user") User user) {return user.toString();
}

使用 @RequestBody 方式传递数据会报错

接收文件
@RequestPart 方式接口及响应
@PostMapping("/part_file")
public String partFile(@RequestPart("file") MultipartFile file) {return file.getOriginalFilename();
}

PS : 一般情况 @RequestBody 注解不支持接收 MultipartFile 类型的数据

异同点
  • 相同点
    • 都可以用实体类接收传参
  • 不同点
    • @RequestPart 仅支持 Content-Type 以 multipart/ (multipart/form-data | multipart/mixed) 开头的 request
    • @RequestPart 可以接收文件类型

@RequestPart vs @RequestParam

接收文件

@RequestPart 方式已经在上文中演示了,这里主要演示 @RequestParam 方式

@RequestParam 方式接口及响应
@PostMapping("/param_file")
public String paramFile(@RequestParam("file") MultipartFile file) {return file.getOriginalFilename();
}

实体类User接收传参

@RequestPart 方式已经在上文中演示了,这里主要演示 @RequestParam 方式

创建UserConfig,添加自定义 convert
@Configuration
public class UserConfig implements WebMvcConfigurer {@Overridepublic void addFormatters(FormatterRegistry registry) {registry.addConverter(new Converter<String, User>() {@Overridepublic <U> Converter<String, U> andThen(Converter<? super User, ? extends U> after) {return Converter.super.andThen(after);}@Overridepublic User convert(String source) {ObjectMapper objectMapper = new ObjectMapper();try {return objectMapper.readValue(source, User.class);} catch (Exception e) {throw new RuntimeException(e);}}});}}
@RequestParam 方式接口及响应
@PostMapping("/param_entity")
public String paramEntity(@RequestParam("user") User user) {return user.toString();
}

PS : 默认情况下, @RequestParam 都以 String 接收传参(非 MultipartFile | Part 类型),然后再遍历当前环境中的 converts,依次尝试将传参转换成指定类型

异同点
  • 相同点
    • 都可以用实体类接收传参
    • 都可以接收文件类型
  • 不同点
    • @RequestPart 依靠 HttpMessageConverter 接收实体类,@RequestParam 依靠 Converter 接收实体类
    • @RequestParam 可以有默认值
    • @RequestParam 可以解析 URL 上的传参
    • 。。。

PS : @RequestParam 功能还是比较强大的,我会在下文贴上博文地址,不同点还有挺多的

源码解析

@RequestPart、@RequestBody、@RequestParam 的源码解析流程大同小异,在之前我已经写了 关于 @RequestParam 、@RequestBody 注解的两篇博文,如果搞懂这两个注解,@RequestPart  注解自然也就懂了。根据我的理解,大概有这样一个公式 @RequestPart  = @RequestBody@RequestParam处理文件类型部分

相关博文链接

  • @RequestBody: @RequestBody注解的使用及源码解析
  • @RequestParam:@RequestParam注解的使用及源码解析

InvocableHandlerMethod#getMethodArgumentValues

参数的处理分为两个阶段:

  1. 判断当前环境中存在的 resolvers,是否支持解析当前参数
  2. 处理参数

判断是否支持解析当前参数

我的环境中存在27个resolvers,通过命名我们大概可以猜测出 RequestPartMethodArgumentResolver 是处理 @RequestPart 注解的 resolver

RequestPartMethodArgumentResolver#supportsParameter

RequestPartMethodArgumentResolver 可以处理两种情况的传参:

  1. 存在 @RequestPart 注解
  2. 不存在 @RequestParam 注解,且参数类型是 MultipartFilePart (或其集合形式)
RequestPartMethodArgumentResolver#resolveArgument

通过源码我们可以得出以下结论:

参数类型是 MultipartFilePart :使用 MultipartResolutionDelegate#resolveMultipartArgument 方法进行处理

其他类型:使用 AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters 方法进行处理

@RequestPart vs @RequestParam 

@RequestParam 基本上是由 RequestParamMethodArgumentResolver 这个类来处理的,我们来看相关源码

RequestParamMethodArgumentResolver#resolveArgument

如果参数类型是 MultipartFilePart,它们都是通过同一个方法处理的

@RequestPart vs @RequestBody

@RequestBody 基本上是由 RequestResponseBodyMethodProcessor 这个类来处理的,我们来看相关源码

RequestResponseBodyMethodProcessor#resolveArgument

 都是调用 readWithMessageConverters 方法进行处理

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com