Spring MVC参数绑定终极手册:单多参/对象/集合/JSON/文件上传精讲

article/2025/8/13 19:13:12

        我们通过浏览器访问不同的路径,就是在发送不同的请求,在发送请求时,可能会带一些参数,本文将介绍了Spring MVC中处理不同请求参数的多种方式

一、传递单个参数

        接收单个参数,在Spring MVC中直接用方法中的参数就可以,如以下代码:

@RequestMapping("Param")
@RestController
public class ParamController {@RequestMapping("a1")public String tex1(String string){return "接收到参数:"+string;}
}

        我们使用Postman传参后,浏览器访问 127.0.0.1:8080/Param/a1?string=Spring

        Spring MVC会根据方法,找到对应的参数,赋值给方法,参数不一致,是获取不到参数,即为null(包装类型)

 注意

        使用基本类型来接收参数时,参数必须传(除boolean类型),否则报500错误;类型不匹配,会报400错误(此处400/500等都是状态码,其他篇章会涉及讲解)

1.1、正常传递参数

@RequestMapping("a2")public Object text2(int a){return "接收到参数a:"+a;}

        通过Fiddler观察请求和响应, HTTP响应状态码为200(正常)

1.2、不传a参数 

         通过Fiddler观察请求和响应, HTTP响应状态码为500(服务器异常)

        尝试观察程序的错误日志,并解决:

        可选的整型参数“a”存在,但由于被声明为基本类型,所以无法转换为 null 值。建议将其声明为对应基本类型的对象包装器。 

1.3、传递参数类型不匹配

 对于包装类型, 如果不传对应参数,Spring 接收到的数据则为null。所以开发中,对于参数可能为空的数据,建议使用包装类型

二、传递多个参数

        和传输一个参数一样,直接使用方法的参数接收即可

@RestController
public class ParamController {@RequestMapping("Param")public String Demo1(String name,String age){return "接收到参数name: "+name+" ,age: "+age;}
}

        使用浏览器发送请求并传参:127.0.0.1:8080/Param?name=小奥奇&age=8

         可以发现,后端程序是正确拿到 name 和 age 参数的值

        当有多个参数时,前后端是以参数的名称进行参数匹配的,但是参数的位置是不影响后端获取参数的结果 

三、传递对象

        如果需要传递的参数较多时,使用方法传参就要有很多形参,并且后续每增加一个参数,也要修改方法的声明,比较麻烦~,在此情况下我们便可以把这些参数封装成一个对象

        Spring MVC 也可以自动实现对象参数的赋值,我们先创建一个 Cat 对象

public class Cat {private String name;private int age;private String hobby;public String getName() {return name;}public int getAge() {return age;}public String getHobby() {return hobby;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setHobby(String hobby) {this.hobby = hobby;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +", age=" + age +", hobby='" + hobby + '\'' +'}';}
}

        实现传递对象的方法

  @RequestMapping("Cat")public Object Cat(Cat cat){return cat.toString();}

         使用浏览器发送请求并传参:127.0.0.1:8080/Cat?name=咪咪&age=1&hobby=喜欢吃小鱼干

        正好对应我们 Cat 类中的三个成员变量,此过程中 Spring 会根据参数名称自动绑定到对象的各个属性上,如果属性未传递,则会赋值位null(基本类型会被赋值为默认初始值,比如 int 赋值 0)

四、后端参数重命名(后端参数映射)

        在一些情况下,前端传递的参数 key 和我们后端接受的 key 可以不一致,比如前端想加密URL中的信息,会使用 p 传递给后端,后端是使用 password 字段来接收的(保证可读性,不然后续维护时,不知道 p 到底是什么),如果出现这种情况,我们可以使用 @RequestParam 来重命名前后端的参数值

 @RequestMapping("A1")public String A1(@RequestParam("p") String password){return "接收参数: password:"+password;}

         该注解表示从前端接收到 p 赋值给 password 

 

        那如果我们直接传递给后端的参数 password 呢?

2025-05-30T22:37:36.378+08:00  WARN 27268 --- [SpringDemo1] [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'p' for method parameter type String is not present]

控制台打印日志显示:请求参数 p 不存在

        那既然是 String 引用类型,我们尝试不传参数试试,会不会得到 null ~~

         我们发现,当不传参数时,直接报客户端错误了,因为当我们使用该注解时,这个参数就变成必传参数了,我们点进该注解的源码中:

         表示:若请求缺失此参数,会抛出 MissingServletRequestParameterException,返回 ​​HTTP 400(Bad Request)​​ 错误,我们可以通过设置该 required 使该参数为非必传参数

@RequestMapping("A1")public String A1(@RequestParam(value = "p",required = false) String password){return "接收参数: password:"+password;}

        将 required 设置为 false ,再次空传参数得到:

结论

        使用 @RequestParam 进行参数重命名时,请求参数只能和 @RequestParam 声明的名称一致,才能进行参数绑定和赋值

        使用 @RequestParam 进行参数重命名时, 参数就变成了必传参数

五、传递数组 

@RequestMapping("A2")public String A2(String[] arr){return "接收参数:arr:"+ Arrays.toString(arr);}

        和传递引用类型一样,直接把数组当成参数,那数组包含多个元素,我们该如何传递呢?

         此外,我们还可以直接使用方式二在一行中传递多个元素:

        可以看到,方式二每个元素是以逗号分隔的,但是如果我们本来就要传递一个逗号呢?

         那么逗号就会转义为%2c

六、传递集合

        集合参数:和数组类似,同一个请求中出现多个同名参数,需要使用@RequestParam绑定参数关系,Spring自动将其值收集到一个集合中

@RequestMapping("A1")public String A1(@RequestParam List<Integer> list){return "接收参数:"+list;}

七、传递JSON数据

7.1、概念

        JSON概念:JSON 全称为 ​​JavaScript Object Notation​​(JavaScript 对象表示法),是一种​​轻量级的数据交互格式​​。

        简单来说JSON就是客户端和服务端进行交互的一种数据格式有自己的格式和语法使用文本表示对一个对象或数组的信息,因此本质上是字符串,主要负责在不同的语言中数据传递和交换

7.2、JSON语法

        还可以压缩为

 {"name":"Json.CN","url":"http://www.json.cn","page":88,"isNonProfit":true,"address":{"street":"科技园路.","city":"江苏苏州","country":"中国"},"links":[{"name":"Google","url":"http://www.google.com"},{"name":"Baidu","url":"http://www.baidu.com"},{"name":"SoSo","url":"http://www.SoSo.com"}]}

        我们可以使用在线JSON格式化工具来进行校验和书写:https://www.bejson.com/

7.3、JSON的优点:

  1. ​简单易用​​:语法简单,易于理解和编写,可以快速进行数据交换。
  2. ​跨平台支持​​:JSON可以被多种编程语言解析和生成,可以在不同的平台和语言之间进行数据交换和传输。
  3. ​轻量级​​:相较于XML格式,JSON数据格式更加轻量级,传输数据时占用带宽较小,可以提高数据传输速度。
  4. ​易于扩展​​:JSON的数据结构灵活,支持嵌套对象和数组等复杂的数据结构,便于扩展和使用。
  5. ​安全性​​:JSON数据格式是一种纯文本格式,不包含可执行代码,不会执行恶意代码,因此具有较高的安全性。

7.4、JSON字符串和Java对象互转

        Spring MVC框架集成了JSON的转换工具,我们可以直接使用来完成两者的互转

        本质上是 jackson-databind 提供的功能,SpringMVC框架中已经把该工具包引入了进来,咱们直接使用即可,如果脱离SpringMVC使用,需要引入相关依赖

        使用 ObjectMapper 对象提供的两个方法,可以完成对象和JSON字符串的互转         writeValueAsString: 把对象转为JSON字符串 readValue: 把字符串转为对象

public class JSONText {@Testpublic void JsontoJava() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//定义一个JSON字符串String s="{\"name\":\"咪咪\",\"age\":1,\"color\":\"blue\"}";//转对象Animals cat=mapper.readValue(s,Animals.class);System.out.println(cat.toString());}@Testpublic void JavatoJson() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//创建Java对象Animals cat = new Animals();cat.setName("cat");cat.setAge(1);cat.setColor("blue");//转换为JSONString str = mapper.writeValueAsString(cat);System.out.println(str);}
}

7.5、传递JSON对象 

        接收JSON对象,需要使用@RequestBody注解

RequestBody​​:请求正文,意思是这个注解作用在请求正文的数据绑定,​​请求参数必须写在请求正文中​​。

@RequestMapping("A3")public String A3(@RequestBody Animals animals){return animals.toString();}

        我们再postman中传入的是JSON格式的字符串,但在后端代码中,Spring会把我们传入的JSON字符串转化成一个对象,我们就不用自己转化为Java对象了,还可以对此对象进行操作:

@RequestMapping("A3")public String A3(@RequestBody Animals animals){System.out.println(animals.getColor());animals.color="彩虹色";return animals.toString();}

八、获取URL中参数@PathVariable

        这个注解主要作用在请求URL路径上的数据绑定(默认传递参数写在URL上,Spring MVC 就可以获取到)

@RequestMapping("A4/{id}")public String A4(@PathVariable Integer id){return "获取id: "+id;}

         我们还可以传递两个参数:

@RequestMapping("A4/{id}/{age}")public String A4(@PathVariable Integer id,@PathVariable Integer age) {return "获取id: "+id+",age: "+age;}

        这两个也默认为必传参数,如果我们只传递一个参数,会发生客户端错误,那么我们是否可以设置为非必传参数

        答案是:理论上可以,但是我们若对改路径传一个参数,那么这个参数是id还是age???Spring也不知道,所以参数是必传的,另外我们可以重命名(此处不再演示)

九、上传文件@RequestPart

 @RequestMapping("A5")public String A5(MultipartFile file) {System.out.println(file.getOriginalFilename());return "文件获取成功";}


http://www.hkcw.cn/article/FvdoWKSiWr.shtml

相关文章

【Go-补充】Sync包

并发编程-Sync包 sync.WaitGroup 在代码中生硬的使用time.Sleep肯定是不合适的&#xff0c;Go语言中可以使用sync.WaitGroup来实现并发任务的同步。 sync.WaitGroup有以下几个方法&#xff1a; 方法名功能(wg * WaitGroup) Add(delta int)计数器delta(wg *WaitGroup) Done()…

M-OFDM模糊函数原理及仿真

文章目录 前言一、M序列二、M-OFDM 信号1、OFDM 信号表达式2、模糊函数表达式 三、MATLAB 仿真1、MATLAB 核心源码2、仿真结果①、m-OFDM 模糊函数②、m-OFDM 距离分辨率③、m-OFDM 速度分辨率④、m-OFDM 等高线图 四、资源自取 前言 本文进行 M-OFDM 的原理讲解及仿真&#x…

《C++初阶之入门基础》【C++的前世今生】

【C的前世今生】目录 前言&#xff1a;---------------起源---------------一、历史背景二、横空出世---------------发展---------------三、标准立世C98&#xff1a;首个国际标准版本C03&#xff1a;小修订版本 四、现代进化C11&#xff1a;现代C的开端C14&#xff1a;对C11的…

长上下文推理新范式!QwenLong-L1如何通过强化学习突破大模型语境局限?

长上下文推理新范式&#xff01;QwenLong-L1如何通过强化学习突破大模型语境局限&#xff1f; 在大模型推理能力不断精进的今天&#xff0c;长上下文处理仍是亟待突破的难题。本文介绍的QwenLong-L1框架&#xff0c;借助渐进式语境扩展与强化学习&#xff0c;成功让大模型在长…

git 学习

目录 关于git 版本管理概述 git的优点 一 下载&#xff0c;安装git 二 使用git 的处理流程 三 学习基本的git命令 1 git初始化 2 查看 状态 3 提交的缓存区 4回退到工作区 关于git 版本管理概述 码云&#xff1a;Gitee - 基于 Git 的代码托管和研发协作平台 git 是用…

中国风展示工作总结商务通用PPT模版

中国风展示工作总结商务通用PPT模版&#xff1a;中国风商务通用PPT 模版https://pan.quark.cn/s/42ad18c010d4

gitflow

gitflow 1. 各个分支介绍 master分支: 源代码 HEAD始终反映出生产就绪状态。仅包含 生产环境可发布的代码&#xff0c;每个提交对应一个正式版本&#xff08;通过 git tag 打版本号&#xff09;一般情况下&#xff0c;只允许合并(如从 release 或 hotfix 分支合并), 禁止直接提…

Python训练营---Day42

DAY 42 Grad-CAM与Hook函数 知识点回顾 回调函数lambda函数hook函数的模块钩子和张量钩子Grad-CAM的示例 作业&#xff1a;理解下今天的代码即可 1、回调函数 回调函数&#xff08;Callback Function&#xff09;是一种特殊的函数&#xff0c;它作为参数传递给另一个函数&#…

Git远程操作

目录 1. 理解分布式版本控制系统 2. 远程仓库 3. 新建远程仓库 4. 克隆远程仓库 4.1 使用HTTPS方式&#xff1a; 4.2 使用SSH方式&#xff1a; 5. 向远程仓库推送 总结&#xff1a; 问题&#xff1a; 6. 拉取远程仓库 7. 配置Git 7.1 忽略特殊文件 8. 给命令配置别…

SolidWorks软件的安装与卸载

文章目录 软件的下载途径软件的安装软件的卸载 简介&#xff1a;这篇文章介绍了SolidWorks软件的安装与卸载&#xff0c;步骤是比较繁琐的&#xff0c;但照着步骤一步一步的来15分钟就能安装成功。这里要特别的注意一点的是&#xff0c;文件的安装位置一定要集中&#xff08;别…

Python 验证码识别(使用pytesseract库)

文章目录 摘要1、安装Tesseract-OCR2、在python中使用安装依赖 3、本地图片识别4、结合playwright动态识别网站验证码 摘要 python中使用pytesseract库进行ocr识别&#xff0c;需要安装Tesseract-OCR&#xff0c;通过指定pytesseract.tesseract_cmd路径&#xff0c;可以将esser…

日志与策略模式

什么是设计模式 IT行业这么火, 涌入的人很多. 俗话说林子大了啥鸟都有. 大佬和菜鸡们两极分化的越来越严重. 为了让菜鸡们不太拖大佬的后腿, 于是大佬们针对一些经典的常见的场景, 给定了一些对应的解决方案, 这个就是 设计模式 日志认识 计算机中的日志是记录系统和软件运行中…

ToolsSet之:XML工具

ToolsSet是微软商店中的一款包含数十种实用工具数百种细分功能的工具集合应用&#xff0c;应用基本功能介绍可以查看以下文章&#xff1a; Windows应用ToolsSet介绍https://blog.csdn.net/BinField/article/details/145898264 ToolsSet中Text菜单下的XML Tool工具是一个Xml工…

2025年目前最新版本Android Studio自定义xml预览的屏幕分辨率

一、前言 在实际开发项目当中&#xff0c;我们的设备的分辨率可能会比较特殊&#xff0c;AS并没有自带这种屏幕分辨率的设备&#xff0c;但是我们又想一边编写XML界面&#xff0c;一边实时看到较为真实的预览效果&#xff0c;该怎么办呢&#xff1f;在早期的AS版本中&#xff…

sql知识梳理(超全,超详细,自用)

目录 通识 查询的基本语法 数据库&#xff08;database&#xff09;操作 表&#xff08;table&#xff09;的操作 表中列的操作 索引操作 表中行的操作 insert into语句 update语句 删除语句 select语句 表与表之间的关系 连接查询 子查询 视图 数据备份与还原 …

数据分析图表类型及其应用场景

说明&#xff1a;顶部HTML文件下载后可以直接查看&#xff0c;带有示图。 摘要 数据可视化作为现代数据分析的核心环节&#xff0c;旨在将复杂、抽象的数据转化为直观、易懂的图形形式。这种转化显著提升了业务决策能力&#xff0c;优化了销售与营销活动&#xff0c;开辟了新…

1、树莓派更换软件下载源

树莓派官方系统raspbian自带的是国外的软件源&#xff0c;在国内使用经常会遇到无法下载软件的问题。 以下是把raspbian系统&#xff08;buster版本&#xff09;的下载源改为阿里云软件源的方法。 1、修改sources.list文件 sudo nano /etc/apt/sources.list 将初始化中的代…

TDengine 集群容错与灾备

简介 为了防止数据丢失、误删操作&#xff0c;TDengine 提供全面的数据备份、恢复、容错、异地数据实时同步等功能&#xff0c;以保证数据存储的安全。本节简要说明 TDengine 中的容错与灾备。 容错 TDengine 支持 WAL 机制&#xff0c;实现数据的容错能力&#xff0c;保证数…

第十五章 访问控制

系列文章目录 第一章 总体概述 第二章 在实体机上安装ubuntu 第三章 Windows远程连接ubuntu 第四章 使用Docker安装和运行EMQX 第五章 Docker卸载EMQX 第六章 EMQX客户端MQTTX Desktop的安装与使用 第七章 EMQX客户端MQTTX CLI的安装与使用 第八章 Wireshark工具的安装与使用 …

LeetCode算法题 (搜索二维矩阵)Day18!!!C/C++

https://leetcode.cn/problems/search-a-2d-matrix/description/ 一、题目分析 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 ta…