@RequestBody

目录

概述

深入细节

案例

@RequestBody与前端传过来的json数据的匹配规则

指定模型中的属性对应什么key

用@Valid校验@RequestBody的参数

根据RequestBody的内容来区分使用哪个资源


概述

  • @RequestBody主要用来接收前端传递给后端的json字符串中的数据(请求体中的数据)
  • 而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交
  • 用途:用于获取HTTP请求的主体内容,通常用于读取非表单数据,如JSON或XML格式
  • 数据绑定:将HTTP请求体中的数据绑定到一个对象上,通常使用转换器如Jackson或Gson将JSON或XML转换成Java对象
  • 使用场景:适用于POST或PUT请求
  • 举例:

深入细节

  • (细节1) 在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用
  • @RequestBody最多只能有一个,而@RequestParam()可以有多个
  • (1)注意:一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam
  • (2)注意:当同时使用@RequestParam()和@RequestBody时,@RequestParam()指定的参数可以是普通元素、数组、集合、对象等等(即:当,@RequestBody与@RequestParam()可以同时使用时,原SpringMVC接收参数的机制不变,只不过RequestBody接收的是请求体里面的数据;而RequestParam接收的是key-value里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象等接收),即:如果参数是放在请求体中,application/json传入后台的话,那么后台要用@RequestBody才能接收到;如果不是放在请求体中的话,那么后台接收前台传过来的参数时,要用@RequestParam来接收,或者形参前什么也不写也能接收
  • (3)注意:如果参数前写了@RequestParam(xxx),那么前端必须有对应的xxx名字才行(不管其是否有值,当然可以通过设置该注解的required属性来调节是否必须传),如果没有xxx名的话,那么请求会出错,报400
  • (4)注意:如果参数前不写@RequestParam(xxx)的话,那么前端如果有xxx名的话,那么就会自动匹配;没有的话,请求也能正确发送
  • 追注1:在Spring MVC中,当HTTP请求到达控制器的处理方法时,Spring会尝试将请求中的参数映射到方法的参数上;这是通过方法参数名称或注解提供的名称来进行的
  • 追注2:如果控制器方法的参数前没有@RequestParam注解,Spring MVC会根据非限定名称来尝试绑定方法参数,这涉及到以下几点行为:
  1. 参数名称匹配:如果HTTP请求中有与方法参数同名的参数,Spring会自动将该值注入到方法参数中
  2. 可选参数:如果HTTP请求中缺少对应同名参数,而方法参数没有使用@RequestParam标记为必需,那么请求仍会被正确映射且方法会被调用;在这种情况下,该参数可能会被赋予一个null值或基本类型的默认值(比如int类型的0);但这种行为可能会让方法中的参数接收到一个不是从请求直接提供的值,这可能会导致潜在的错误,除非有适当的空值处理逻辑
  3. 不明确的行为:如果没有@RequestParam明确指定参数,且请求中也没有同名参数,那么方法参数的值究竟是什么,可能不是那么明确;这可能取决于参数的类型及是否有默认构造方法等因素
  4. 参数类型转换:Spring会尝试将请求参数转换为方法参数的类型(例如,从字符串转换为整数);如果转换失败,可能会导致请求处理失败
  • 下面是一个无@RequestParam注解的例子:
  • 在这个例子中,如果请求中有category这个参数,那么它的值会被传递到category方法参数中
  • 如果没有,该方法参数的值将为null(对于对象)或基本类型的默认值
  • 综上所述,使用@RequestParam让你可以更明确地表达你期待的请求行为,包括参数是否必须、默认值是什么等
  • 而不使用注解,则采取更隐式的绑定方式,参数可有可无,当它们存在时会被匹配和使用;不存在时,请求也能正确发送,但你的方法应当能处理这种情况
  • 追注3:这里与feign消费服务时不同;feign消费服务时,如果参数前什么也不写,那么会被默认是@RequestBody的
  • (细节2) 如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:
  1. 后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为)(这一条会在下面详细分析)实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性
  2. json字符串中,如果value为""的话,后端对应属性如果是String类型的,那么接受到的就是"",如果后端属性的类型是Integer、Double等类型,那么接收到的就是null
  3. json字符串中,如果value为null的话,后端对应收到的就是null
  4. 如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时,必须有值,null或""都行;千万不能有类似"stature":,这样的写法,如:

案例

  • 先给出两个等下要用到的实体类
  • User实体类:
  • Team实体类:
  • @RequestBody直接以String接收前端传过来的json数据:
  • 后端对应的Controller:
  • 使用PostMan测试:
  • @RequestBody以简单对象接收前端传过来的json数据:
  • 后端对应的Controller:
  • 使用PostMan测试:
  • @RequestBody以复杂对象接收前端传过来的json数据:
  • 后端对应的Controller:
  • 使用PostMan测试(传递的json字符串中必须要有key,否则请求会出错):
  • @RequestBody与简单的@RequestParam()同时使用:
  • 后端对应的Controller:
  • 使用PostMan测试:
  • @RequestBody与复杂的@RequestParam()同时使用:
  • 后端对应的Controller:
  • 使用PostMan测试:
  • @RequestBody接收请求体中的json数据;不加注解接收URL中的数据并组装为对象:
  • 后端对应的Controller:
  • 使用PostMan测试:
  • 注意:如果在后端方法参数前,指定了@RequestParam()的话,那么前端必须要有对应字段才行(当然可以通过设置该注解的required属性来调节是否必须传),否则会报错;如果参数前没有任何该注解,那么前端可以传这个参数,也可以不传,如:
  • 上图中,如果我们传参中没有指定token,那么请求能正常进去,但是token为null;如果在String token前指定了@RequestParam(“token”),那么前端必须要有token这个键,请求才能正常进去,否则报400错误

@RequestBody与前端传过来的json数据的匹配规则

  • 声明:根据不同的Content-Type等情况,Spring-MVC会采取不同的HttpMessageConverter实现来进行信息转换解析
  • 说明:request的body部分的数据编码格式由header部分的Content-Type指定
  • 下面介绍的是最常用的:前端以Content-Type为application/json,传递json字符串数据;后端以@RequestBody模型接收数据的情况
  • 解析json数据大体流程概述:Http传递请求体信息,最终会被封装进com.fasterxml.jackson.core.json.UTF8StreamJsonParser中(提示:Spring采用CharacterEncodingFilter设置了默认编码为UTF-8),然后在public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable中,通过 public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException方法进行解析
  • 核心逻辑分析示例:
  • 假设前端传的json串是这样的: {"name1":"兔子队列","age":20,"mot":"好焦虑"} 后端的模型只有name和age属性,以及对应的setter/getter方法
  • 给出一般用到的deserializeFromObject(JsonParser p, DeserializationContext ctxt)方法的核心逻辑:

指定模型中的属性对应什么key

  • 给出Controller中的测试类:
  • 给出模型中的属性(setter/getter方法没截出来):
  • 使用postman测试一下,示例:
  • 解释1:@JsonAlias注解,实现:json转模型时,使json中的特定key能转化为特定的模型属性;但是模型转json时,对应的转换后的key仍然与属性名一致,见:上图示例中的name字段的请求与响应;以下图进一步说明:
  • 此时,json字符串转换为模型时,json中key为Name或为name123或为name的都能识别
  • 解释2:@JsonProperty注解,实现:json转模型时,使json中的特定key能转化为指定的模型属性;同样的,模型转json时,对应的转换后的key为指定的key,见:示例中的motto字段的请求与响应;以下图进一步说明:
  • 此时,json字符串转换为模型时,key为MOTTO的能识别,但key为motto的不能识别
  • 解释3:@JsonAlias注解需要依赖于setter、getter,而@JsonProperty注解不需要
  • 解释4: 在不考虑上述两个注解的一般情况下,key与属性匹配时,默认大小写敏感
  • 解释5: 有多个相同的key的json字符串中,转换为模型时,会以相同的几个key中,排在最后的那个key的值给模型属性复制,因为setter会覆盖原来的值;见示例中的gender属性
  • 解释6: 后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为)实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性

用@Valid校验@RequestBody的参数

  • 如果希望通过注解校验post请求的body,需要用到@Valid注解
  • 在接收request实体类添加注解进行校验,例如用@NotNull进行判空校验
  • 如果入参是List,单独用@Valid不生效,需要在Controller上加@Validated注解
  • 结合统一异常处理,处理MethodArgumentNotValidException和ConstraintViolationException,可以返回注解配置的错误信息:

根据RequestBody的内容来区分使用哪个资源

  • 如果使用Spring,可以通过@RequestBody将请求体的json转换为Java对象,但如果URI相同,而请求体的内容不同,应该怎么办?
  • 问题来源(stackoverflow):
  • Spring @RequestBody without using a pojo?
  • 稍微研究了一下,如果将@RequestBody指定为Map,那么请求体(键、值)会存储到Map对象中
  • 案例:
  • 发送POST请求,虽然URI相同,但是请求体却不同
  • 不过,携带了一个名为type的共同数据,并通过type的值来判别不同的情况
  • 这次准备了两个type的值:concert和trip
  • 控制器的实现:
  • 在控制器的实现中,指定 @RequestBody 为 Map<String, Object> 类型
  • 通过指定 Map,可以将请求体以键值对的形式存储
  • 查看 type 键的值,以此判断是哪一种类型的请求,并将请求转换为相应的类
  • 在转换过程中使用了 Jackson 的 ObjectMapper 类进行转换
  • 这里,我们将其转换为相应类的对象,输出到标准输出并结束
  • 尝试发送 concert 的请求
  • 结果的标准输出
  • 尝试发送 trip 的请求
  • 结果的标准输出
  • 所以正确地将其转换为对应的类是可能的
  • 整体代码:

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

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

相关文章

【中级软件设计师】上午题02-程序设计语言

上午题02-程序设计语言 1 编译程序和解释程序2 程序设计语言基本成分3 传值调用与传引用调用4 编译器的工作阶段4.1 编译方式和解释方式4.2 符号表4.3 词法、语法、语义分析与目标代码生成4.4 程序异常和错误4.5 中间代码 5 正规式 1 编译程序和解释程序 解释器&#xff1a; 翻…

LeetCode - 寻找数组的中心

先学习一下前缀和吧 LCR 012.寻找数组的中心LCR 012. 代码解析 在读题读到左侧元素之和等于右侧所有元素之和的时候&#xff0c;我觉得可以用前缀和&#xff0c;然后结合下面的示例&#xff0c;模拟了一下发现确实可以。 我的想法是搞两个数组&#xff0c;一个来存从左到右数…

Halcon测量专栏-圆弧测量

1.前言 1.1什么是圆弧 圆上任意两点间的部分叫做圆弧。由于圆弧有正反的特性&#xff0c;即为有顺时针方向和逆时针方向&#xff0c;在确定圆弧时&#xff0c;也需要确定圆弧的方向。 1.2halcon实现方式 针对圆弧的问题。1&#xff1a;它与圆是相似的&#xff0c;都具备中心…

视频监控汇聚管理系统EasyCVR平台RTMP推流异常是什么原因?

AI视频智能分析/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff08;专网、内网、局域网、广域网、公网等&#xff09;&#xff0c;支持设备通过4G、5G、WIFI、有线等方式接入&#xff0c;并将设备进行统一集中接入与视频汇聚管理&#xff0c;经平台接入的视频流能实现多…

王道机试C++第 5 章 数据结构二:队列queue和21年蓝桥杯省赛选择题Day32

目录 5.2 队列 1&#xff0e;STL-queue 课上演示&#xff1a; 基本代码展示&#xff1a; 2. 队列的应用 例:约瑟夫问题 No. 2 题目描述&#xff1a; 思路提示&#xff1a; 代码展示&#xff1a; 例&#xff1a;猫狗收容所 题目描述&#xff1a; 代码表示&#xff1…

安防视频监控汇聚平台EasyCVR使用RTMP推流出现异常的原因排查与解决

AI视频智能分析/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff08;专网、内网、局域网、广域网、公网等&#xff09;&#xff0c;支持设备通过4G、5G、WIFI、有线等方式接入&#xff0c;并将设备进行统一集中接入与视频汇聚管理&#xff0c;经平台接入的视频流能实现多…

大数据开发 hadoop集群 2.hadoop框架入门

自从我学会了寻找&#xff0c;我就已经找到 ——史铁生 —— 24.3.10 内容简介 Hadoop入门&#xff1a; ①概念 ②环境准备 ③hadoop生产集群搭建 ④常见错误的解决方案 ①概念&#xff1a;1.Hadoop是什么 2.Hadoop发展历史 3.Hadoop…

【Linux】线程封装_互斥

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;线程封装Thread.cpp &#x1f449;&am…

骨传导耳机哪个牌子好?五大热门品质机型盘点,体验超赞!

在蓝牙耳机中&#xff0c;骨传导耳机凭借不入耳佩戴更健康等优点&#xff0c;迅速成为当下的热门款式&#xff0c;但随着骨传导耳机市场的品牌日渐增多&#xff0c;以及市场上不专业的骨传导耳机泛滥成灾的问题&#xff0c;有很多消费者在选择骨传导耳机的时候&#xff0c;都出…

【算法】Hash存储——开放寻址法

模拟散列表 维护一个集合&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个整数 x&#xff1b; Q x&#xff0c;询问整数 x是否在集合中出现过&#xff1b; 现在要进行 N次操作&#xff0c;对于每个询问操作输出对应的结果。 输入格式 第一行包含整数 N&am…

代码随想录 贪心算法-中等题目-序列问题

376.摆动序列 376. 摆动序列 中等 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7…

spring boot 访问 static public 目录下的静态资源报404解决办法

1.前提是你没有修改spring boot 默认拦截路径&#xff0c;跟默认访问资源的目录。 在idea 设置中 把 compiler 下的 Buid project automatically 勾选上

开源的java视频处理库介绍

本文将为您详细讲解 Java 开源的视频处理库&#xff0c;以及它们的特点、区别和应用场景。Java 社区提供了多种视频处理库&#xff0c;这些库可以帮助您在 Java 应用程序中实现视频的录制、编辑、转换和播放等功能。 1. JCodec 特点 - 基于 Java 的视频编解码库。 - 支…

ChatGpt只能看,但无法发送消息的解决办法

这几天发现chatgpt没法发送消息了,我以为是网络问题,又过了几天还是不能发,我以为是梯子的问题,可给我急坏了,于是我用无痕模式发现可以访问额. 但是无痕模式毕竟不是长久之计,于是找到了一个方法 1.首先把电脑缓存全清除了 第一种方法: 快捷键是 : ctrlshiftdel (这会吧浏览…

分支需求管理方式

此文为上一篇文章的后续 我们来回顾一下&#xff0c;现在&#xff0c;你的小组负责的系统&#xff0c;有主干分支&#xff0c;每次新的需求&#xff0c;你都从主干(formal)拉取分支(dev-日期-需求名)进行修改&#xff0c;自测通过后&#xff0c;合并至测试分支(test)进行提测&a…

Python高级二

一、异常 1、定义 异常是在程序执行过程中出现的错误或意外情况。当程序遇到异常时&#xff0c;它会中断当前的执行流程&#xff0c;并尝试找到相应的异常处理机制来解决问题。 2、常见异常类型 SyntaxError&#xff1a;语法错误&#xff0c;通常是代码书写不符合Python语法规则…

VSCode单机活动栏图标无法收起

如果活动栏为展开状态&#xff0c;单击活动栏图标可以正常收起&#xff0c;但无法通过再次单击打开&#xff0c;解决方案如下&#xff1a; 设置->工作台->外观&#xff1a; Activity Bar:Icon Click Behavior: 切换为默认的toggle

C++ 作业 24/3/11

1、提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数&#xff08;要求使用C风格字符串完成&#xff09; #include <iostream>using namespace std;int main() {string str;cout << "please enter str:&…

【Flutter 面试题】如何理解Flutter中的Widget、State、Context ,他们是为了解决什么问题?

【Flutter 面试题】如何理解Flutter中的Widget、State、Context &#xff0c;他们是为了解决什么问题&#xff1f; 文章目录 写在前面解答补充说明完整代码示例运行结果如下详细说明 写在前面 &#x1f64b; 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff…

svg简单教程

推荐查看这个视频 一小时讲完SVG 简介 scalable 英 /ˈskeɪləbl/ 美 /ˈskeɪləbl/ adj. &#xff08;计算机&#xff09; 可扩展的&#xff1b;可改变大小的&#xff0c;可缩放的&#xff1b;可攀登的&#xff1b;可称量的&#xff1b;可去鳞的 vector 英 /ˈvektə/ 美…