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

news2024/9/28 7:17:45

前言

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

案例演示

创建实体类 User

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private String username;

    private String password;

    @Override
    public 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 {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new Converter<String, User>() {

            @Override
            public <U> Converter<String, U> andThen(Converter<? super User, ? extends U> after) {
                return Converter.super.andThen(after);
            }

            @Override
            public 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 方法进行处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1914206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图片海报怎么做成二维码展示?二维码分享图片的制作技巧

怎么把图片的宣传海报做成二维码呢&#xff1f;在做活动或者产品宣传时&#xff0c;都会制作精美的图片海报&#xff0c;除了打印传单或者制作展板的方式来展示外&#xff0c;将海报图片生成二维码&#xff0c;通过分享二维码来实现图片海报的快速传播&#xff0c;能够有效提升…

[数据结构] 基于插入的排序 插入排序希尔排序

标题&#xff1a;[数据结构] 排序#插入排序&希尔排序 水墨不写bug 目录 &#xff08;一&#xff09;插入排序 实现思路&#xff1a; 插入排序实现&#xff1a; &#xff08;二&#xff09;希尔排序 希尔排序的基本思想&#xff1a; 希尔排序的实现&#xff1a; 正…

【转】-java多线程读写锁ReadWriteLock

Java多线程中读写锁ReadWriteLock的使用 该博客转载自​**lavimer​的​Java多线程中读写锁ReadWriteLock的使用** 1. 概念 读写锁分为读锁和写锁&#xff0c;多个读锁之间是不需要互斥的(读操作不会改变数据&#xff0c;如果上了锁&#xff0c;反而会影响效率)&#xff0c;…

IPXProxy海外代理IP在MultiLogin指纹浏览器中的配置教程

Multilogin指纹浏览器是一款付费浏览器&#xff0c;它为用户提供了拥有多个虚拟浏览器配置文件的机会。作为最好的指纹浏览器之一&#xff0c;它常常被用来创建或管理多个账户&#xff0c;当然在这个过程&#xff0c;代理IP是不可或缺的一部分。下面给大家代理在MultiLogin指纹…

【企业级监控】Docker部署Zabbix与监控主机

基于Docker部署Zabbix6.2 文章目录 基于Docker部署Zabbix6.2资源列表基础环境一、首先安装Docker1.1、部署Docker1.2、配置Docker加速器 二、部署Zabbix组件介绍三、部署Zabbix3.1、安装数据库容器3.2、安装zabbix-java-gateway3.3、安装zabbix-server3.4、安装zabbix-web界面3…

大数据下的用户研究:深度洞察与精准决策的引擎

文章目录 一、大数据时代的用户研究新机遇二、大数据用户研究的流程与关键技术三、大数据用户研究的实践案例四、大数据用户研究的挑战与展望《用户研究方法&#xff1a;卓越产品和服务的用户研究技巧》内容及特色读者对象 在当今这个数据爆炸的时代&#xff0c;大数据已成为推…

microblaze时钟更改出现时序问题

在使用microblaze时&#xff0c;我给的时钟是200MHz的时钟&#xff0c;但会在跑布线的时候出现时序上的问题&#xff0c;一开始是没有任何的头绪&#xff0c;知道我尝试更改时钟的频率才发现问题的所在。 当我把200MHz的时钟改为100MHz的时钟时&#xff0c;就不会出现时序上的…

Defensor 4.5:构建数据资产为中心的安全运营体系

5月31日“向星力”未来数据技术峰会上&#xff0c;星环科技重磅发布数据安全管理平台 Defensor 4.5版本。新版本引入了以数据资产为中心的数据安全运营体系&#xff0c;通过智能化大模型技术&#xff0c;帮助企业快速、精准地识别核心重要资产&#xff1b;建设全局的数据安全策…

全球数字贸易中心解析_保税区保的是什么税_为什么保税区还要交税

保税区税收机制深度解析&#xff1a;保税免的是什么税&#xff1f;为何仍需缴税&#xff1f; 保税区概述 保税区&#xff0c;作为海关特殊监管区域的重要一环&#xff0c;享有国家高度开放的政策优惠与功能齐全的海关监管服务。它专为保税加工、保税物流和保税服务而设&#…

安防管理平台LntonCVS视频汇聚融合云平台智慧火电厂安全生产管理应用方案

中国的电力产业作为国民经济发展的重要能源支柱&#xff0c;被视为国民经济的基础产业之一。目前&#xff0c;我国主要依赖火力发电&#xff0c;主要燃料包括煤炭、石油和天然气等&#xff0c;通过燃烧转化为动能&#xff0c;再转变为电能输送至全国各地。火力发电量占全国发电…

给你的博客加上评论区

一个网站如果有评论功能&#xff0c;可以更好的和读者互动。VuePress 也有很多评论插件&#xff0c;这里简单介绍下&#xff0c;最后介绍本站所使用的 Twikoo。 大部分评论插件都是使用的 Github 或 Gitee 的 issue 功能&#xff0c;也就是用 issue 去存储评论&#xff1b;而 …

高压线束屏蔽效能测试之管中管法、线注入法

一、引言 上期推文介绍了高压线束屏蔽效能测试方法三同轴法&#xff0c;本篇文章将继续介绍高压线束相关测试方法——管中管法和线注入法。 二、管中管法 1、一般要求 管中管法参照IEC62153-4-7标准对高低压连接器进行零部件级屏蔽效能测试。在测试时&#xff0c;通过金属延长管…

从零开始做题:MP3

题目 给出一个mp3文件 解题 右键->selection->save selection->另存为xxx.png即可 8750d5109208213f E:\逐鹿\MISC\tools\MP3Stego_1_1_19\MP3Stego>.\decode -X cipher.mp3 MP3StegoEncoder 1.1.19 See README file for copyright info Input file cipher.mp3…

必看!微信小程序必备证书!

微信小程序必备SSL证书。在日益增长的数字经济中&#xff0c;微信小程序已成为商家与消费者之间重要的交互平台。由于其便捷性和广泛的用户基础&#xff0c;越来越多的企业选择通过小程序来提供服务。然而&#xff0c;在开发和部署微信小程序时&#xff0c;确保数据安全是一个不…

three-platformize 微信小程序 uniapp 使用截图功能

最近需要将3d场景进行截图&#xff0c;但是网上的各种各样&#xff0c;看的我一团乱麻&#xff0c;因此在解决完后就将这些简单的分享一下&#xff1b; 原理&#xff1a;将3维场景的那个canvas中的像素提取出来&#xff0c;找一个空的canvas二维画布放上去&#xff0c;然后用二…

Conformal low power-1.概述

概述 设计师们越来越期望更长的电池寿命和更高的性能。由于漏电流的增加&#xff0c;使用90纳米及更小工艺节点制造的设备在不使用时的功耗与使用时相同。设计师们可以针对漏电流和动态功耗进行优化&#xff0c;这可以减少能源使用并降低冷却和封装成本。额外的高级低功耗方法…

oracle哪些后台进程不能杀?

oracle 有很多的后台进程&#xff0c;在遇到特殊情况的时候如锁表&#xff0c;如果等待的是一个后台进程&#xff0c;那这时就需要考量是不是能杀掉这个后台进程&#xff1f;杀掉这个后台进程会不会引起实例崩溃&#xff1f;本着实践出真知&#xff0c;本文针对oracle 11g&…

入门PHP就来我这(高级)20 ~ 事务处理

有胆量你就来跟着路老师卷起来&#xff01; -- 纯干货&#xff0c;技术知识分享 路老师给大家分享PHP语言的知识了&#xff0c;旨在想让大家入门PHP&#xff0c;并深入了解PHP语言。 接着上篇我们来看下PDO数据库的事务处理。 1 PDO中的事务处理 1.1 事务相关概念 事务&#…

基于cmake为项目自动获取git分支tag的版本号和commitid

目录 1. 引言2. 实现过程2.1 工程目录规划2.2 c程序文件2.3 CMakeLists.txt2.4 GitVersion.cmake文件2.5 BuildNumber.cmake文件1. 引言 在项目构建的时候,我们经常会希望能够将git提交的分支信息和提交号(commitid)以及当前版本发布的tag信息作为版本号自动构建到程序里面,以…