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

前言

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python requests爬虫

Python的requests库是一个强大且易于使用的HTTP库&#xff0c;用于发送HTTP请求和处理响应。它是Python中最受欢迎的网络爬虫框架之一&#xff0c;被广泛用于从网页中提取数据、爬取网站和进行API调用。 使用requests库&#xff0c;你可以轻松地发送各种HTTP请求&#xff0c;包…

提示词工程(Prompt Engineering)是什么?

一、定义 Prompt Engineering 提示词工程&#xff08;Prompt Engineering&#xff09;是一项通过优化提示词&#xff08;Prompt&#xff09;和生成策略&#xff0c;从而获得更好的模型返回结果的工程技术。 二、System message 系统指令 System message可以被广泛应用在&am…

linux自动化内存监控与告警

文章目录 前言一、脚本实现1. shell脚本实现2. 脚本功能概览 二、设置定时执行1. 编辑cron任务表2. 设置定时任务 三、通知结果示例总结 前言 在当今数字化与网络化日益普及的时代&#xff0c;系统管理与维护成为了确保业务连续性和数据安全的关键环节。其中&#xff0c;监控系…

大模型时代:人工智能与大数据平台的深度融合

在当今的大数据时代&#xff0c;数据已经成为驱动业务增长和创新的关键因素。与此同时&#xff0c;随着人工智能技术的不断进步&#xff0c;AI在大规模数据处理和分析方面的能力日益强大。因此&#xff0c;将人工智能与大数据平台相结合&#xff0c;可以为企业带来巨大的商业价…

linux信息收集与提权

目录 版本信息收集 kali得一些exp网站 kali自带的searchsploit工具 脏牛提权漏洞&#xff08;改写没有写权限的文件&#xff09; 测试靶场下载链接 sudo提权 上传恶意C脚本进行编译生成dirty的elf文件&#xff0c;也可以在攻击机编译好上传 启动&#xff0c;123456是设…

网站地址显示不安全怎么办

当网址栏显示不安全时&#xff0c;通常是因为网站使用的是HTTP而不是HTTPS协议&#xff0c;或者因为网站的SSL证书存在问题。以下是一些解决方法&#xff1a;1、迁移到HTTPS&#xff1a;如果您是网站所有者&#xff0c;最好的解决方法是将网站迁移到HTTPS。HTTPS通过使用SSL/TL…

室内精准定位是什么?室内精准定位的方式有哪些?

说到室内精准定位很多人可能会比较陌生&#xff0c;因为这一说法并没有大范围推广&#xff0c;又或者说只是很多相关行业的人才知道这样的说法。但是定位这一问题大家都知道吧&#xff1f;尤其是要到一个地方去&#xff0c;都会进行定位导航。那么这一般都是户外定位&#xff0…

案例分享:Qt modbusTcp调试工具(读写Byte、Int、DInt、Real、DReal)(当前v1.0.0)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/140313789 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片…

哈喽GPT-4o,程序员如何通过GPT-4o提高办公效率

目录 一、编写工作汇报Prompt&#xff1a;我是一名Java开发工程师&#xff0c;请写一份工作总结&#xff0c;工作内容是一个SpringBootVue实现的图书管理系统&#xff0c;按下面的结构来撰写&#xff1a;1. 工作背景&#xff1b;2. 工作内容&#xff1b;3. 工作建议&#xff1b…

fastadmin框架后台列表固定第一行列表固定头部

在列表中,如果列表字段很多,并且每页数量很多,往下拉的时候就不好辨别数据是哪个字段的,对用户造成不好的浏览体验。 通过以下方法,可以实现将列表的第一行,也就是头部,固定在第一行显示,这样就能轻松辨别每个数据对应是哪个字段的,增加用户的使用体验。 打开项目的…

【漏洞复现】WordPress插件Recall CVE-2024-32709 SQL注入漏洞

0x01 产品简介 WordPress是一款免费开源的内容管理系统(CMS)&#xff0c;最初是一个博客平台&#xff0c;但后来发展成为一个功能强大的网站建设工具&#xff0c;适用于各种类型的网站&#xff0c;包括个人博客、企业网站、电子商务网站等&#xff0c;并逐步演化成一款内容管理…

PHP酒店宾馆民宿多商户版系统小程序源码

解锁酒店新境界&#xff01;揭秘多商户版系统的无限可能&#x1f3e8;✨ &#x1f680; 开篇&#xff1a;酒店业的新革命&#xff0c;多商户版系统来袭&#xff01; 你是否梦想过将你的酒店打造成一个集餐饮、娱乐、购物于一体的综合型休闲空间&#xff1f;现在&#xff0c;这…

传统剪纸遇上AI绘画:一场跨时代的艺术对话

本文由 ChatMoney团队出品 剪纸&#xff0c;听起来就很有画面感&#xff0c;承载着中国几千年的文化。一把剪刀、一张红纸&#xff0c;轻轻剪几剪&#xff0c;就能幻化出各种栩栩如生的图案。这门艺术不仅仅是视觉上的享受&#xff0c;更是一种感情的传递&#xff0c;一种文化的…

Objective-C 中的 isa 不再是简单的结构体指针

了解 Objective-C 中的 isa 指针内存结构 在 Objective-C 中&#xff0c;isa 指针是对象和类之间的重要桥梁。它不仅帮助运行时系统识别对象的类型&#xff0c;还参与了一些内存和性能优化。本文将深入讲解 isa 指针的内存结构&#xff0c;包括其在早期和现代实现中的演变。 …

【3】A-Frame上手开发

一、JavaScript、事件、DOM API 由于 A-Frame 只是 HTML&#xff0c;因此我们可以使用 JavaScript 和 DOM API 来控制场景及其实体&#xff0c;就像我们在普通 Web 开发中所做的那样。 场景中的每个元素&#xff0c;甚至诸如 <a-box> 或 <a-sky> 之类的元素&…

SpringBootV12和mybatis全部知识点

框架: 快速开发项目的一个架子 ssh ssm spring --> applicationContext.xml配置文件(spring不是业务层,是管理其他框架的) springmvc --> springmvc.xml配置文件 (对应之前servlet) mybatis —> mybatis-config.xml配置文件(对应之前jdbc) —> springboot优化…

平凉崆峒区特产美食亮相兰洽会文旅康养展馆

在第三十届兰洽会的文旅康养展馆中&#xff0c;平凉的特产无疑是一道亮丽的风景线。作为促进区域经济合作与交流的重要平台&#xff0c;每年都吸引着众多企业和特色产品的亮相。 走进这个充满活力与特色的展馆&#xff0c;首先映入眼帘的是琳琅满目的特色产品。平凉红牛的…

python入门综合篇—资源爬取与exe打包(图形界面)

了解我的人都知道&#xff0c;我是一个谨言慎行且兴趣爱好广泛的IT&#xff0c;作为一个合格的前端&#xff0c;没事捣鼓一下python很合理吧&#xff0c;再没事搞搞java和php也很合乎逻辑吧&#xff0c;实在没事&#xff0c;玩玩linux服务器也是合乎常理的吧。所以&#xff0c;…

会员运营体系设计及SOP梳理

一些做会员的经验和方法分享给大家&#xff0c;包括顶层思考、流程的梳理、组织的建立&#xff0c;后续会做成系列&#xff0c;最近几期主要围绕顶层策略方面&#xff0c;以下是核心内容的整理&#xff1a; 1、会员运营体系设计 顶层设计与关键业务定位&#xff1a;建立客户运营…

【JVM基础篇】Java垃圾回收器介绍

垃圾回收器&#xff08;垃圾回收算法实现&#xff09; 垃圾回收器是垃圾回收算法的具体实现。由于垃圾回收器分为年轻代和老年代&#xff0c;除了G1&#xff08;既能管控新生代&#xff0c;也可以管控老年代&#xff09;之外&#xff0c;新生代、老年代的垃圾回收器必须按照ho…