Springmvc-@RequestBody

SpringBoot-2.7.12

请求的body参数无法转换,服务端没有报错信息打印,而是响应的状态码是400

@PostMapping("/static/user")
public User userInfo(@RequestBody(required = false) User user){user.setAge(19);return user;
}

image-20240126215324187

@PostMapping("/static/requiredUser")
public User requiredUserInfo(@RequestBody() User user){log.info(gson.toJson(user));user.setAge(19);return user;
}

image-20240126215757844

SpringBoot-2.1.14.RELEASE

对应springframe一系列版本spring-web、spring-webmvc…版本5.1.15.RELEASE

image-20240126220714423

请求体参数无法接受,没有报错

@PostMapping("/static/requiredUser")
public User requiredUserInfo(@RequestBody() User user){log.info(gson.toJson(user));user.setAge(19);return user;
}

image-20240126221057373

无body及日志输出原因

是因为我这里有一段全局异常处理,但是这里的异常处理返回信息的结果和我上面接口的返回结果不一致。将断点打在这里,也会发现异常并没有进来(进来就会有错误日志了)。是因为我的全局异常类继承了ResponseEntityExceptionHandler这个类导致的。

发现去掉这个全局异常处理,响应结果如下:

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {private final Log log = LogFactory.getLog(this.getClass());@ExceptionHandler(Exception.class)@ResponseBodyReturnInfo handleControllerException(HttpServletRequest request, Throwable ex) {HttpStatus status = getStatus(request);//return new ReturnInfo(status.value(), ex.getMessage());log.error(status.value(),ex);return ReturnInfo.buildErrorInfo(ex.getMessage());}private HttpStatus getStatus(HttpServletRequest request) {Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");if (statusCode == null) {return HttpStatus.INTERNAL_SERVER_ERROR;}return HttpStatus.valueOf(statusCode);}
}

image-20240127093318328

image-20240127093358907

全局异常处理修改

// 只监听这个的下面的异常处理
@ControllerAdvice(assignableTypes = {ExampleController.class})

ResponseEntityExceptionHandler

这个类里面有定义处理HttpMessageNotReadableException异常,这个指定特定异常的优先级可能更高,所以先在这里处理了,但是因为返回的结果类型不匹配,所以最终的响应体是空。

image-20240127100754414

请求体参数属性首字母小写

当出现属性变量名首字母小写时,idea自动生成的get/set格式是set/get[a-z][A-Z].*,首字母会小写,此时你的json的key是属性名,参数是能正常接受的。但是如果将set/get格式换成set/get[A-Z][A-Z].*格式,就会接收不到参数,说明Spring的自动解析参数是set或get方法来的。测试发现,参数接收/响应结果会根据类的get/set中的一个来确定属性的key,例如:

存在一个类中有属性iName,启中只有满足setiName/getiName一项,这个时候使用下面格式就能接收参数

{"iName" : "iName"}

如果都不满从setiName/getiName,而是setIName;getIName,则只能使用下面格式接收参数(并且响应的key和传递一样):

{"iname" : "iname"}

dto1

public class Goods {private String name;private String iName;private String description;private String iDescription;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getIName() {return iName;}public void setIName(String iName) {this.iName = iName;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getIDescription() {return iDescription;}public void setIDescription(String iDescription) {this.iDescription = iDescription;}
}

传参格式:

{"name": "name","description": "description","iname": "iname","idescription": "idescription"
}

响应结果

{"name": "name","description": "description","iname": "iname","idescription": "idescription"
}

dto2

public class Goods {private String name;private String iName;private String description;private String iDescription;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getiName() {return iName;}public void setiName(String iName) {this.iName = iName;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getiDescription() {return iDescription;}public void setiDescription(String iDescription) {this.iDescription = iDescription;}
}

接收参数:

{"name": "name","description": "description","iName": "iName","iDescription": "iDescription"
}

响应结果:

{"name": "name","description": "description","iName": "iName","iDescription": "iDescription"
}

dto3

两种方式都存在,没有属性结果都被返回

public class Goods {private String name;private String iName;private String description;private String iDescription;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getIName() {return iName;}public void setIName(String iName) {this.iName = iName;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getIDescription() {return iDescription;}public void setIDescription(String iDescription) {this.iDescription = iDescription;}public String getiName() {return iName;}public void setiName(String iName) {this.iName = iName;}public String getiDescription() {return iDescription;}public void setiDescription(String iDescription) {this.iDescription = iDescription;}
}

image-20240127111037541

请求体解析

在AbstractJackson2HttpMessageConverter调用read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)方法解析请求体

  • type:@RequestBody注解的类
  • contextClass:被代理处理的controller接口类
  • inputMessage:HTTP请求体的消息

image-20240128132835031

获取要转换的请求的参数类型Type进行解析

image-20240128133804873

TypeVariable处理逻辑:

  1. 根据这个泛型参数所在的类,new ResolvableType(clazz)对象;
  2. 最终是要获取泛型所代表的具体类型

image-20240128134825773

ParameterizedType支持嵌套处理

image-20240128140440376

根据前面获取到的Type类型,是要ObjectMapper对象构建JavaType对象。

image-20240128140919917

最终使用ObjectMapper结合JavaType和输入流得到对象。默认的解析和转换都是以Jackson的规则来的

Jackson使用测试

public class JacksonUtil {private static final ObjectMapper objectMapper = new ObjectMapper();public static JavaType getJavaType(Type type){return objectMapper.getTypeFactory().constructType(type);}/*** 字符串转Java对象* @param json json字符串* @param javaType 最终解析的Java对象类Type对应的JavaType* @return 泛型对象* @param <T>*/public static <T> T stringToObject(String json, JavaType javaType){try {return objectMapper.readValue(json, javaType);} catch (IOException e) {throw new RuntimeException(e);}}/*** 输入流json转Java对象* @param inputStream json输入流* @param javaType 最终解析的Java对象类Type对应的JavaType* @return*/public static Object inputStreamToObject(InputStream inputStream, JavaType javaType){try {return objectMapper.readValue(inputStream, javaType);} catch (IOException e) {throw new RuntimeException(e);}}/**** @param json json字符串* @param clazz 结果类* @return json解析结果对象* @param <T>*/public static <T> T stringToClass(String json, Class<T> clazz){try {return objectMapper.readValue(json, clazz);} catch (IOException e) {throw new RuntimeException(e);}}/*** 对象转json字符串* @param object 要转成json的对象* @param javaType 对象的Type对应的JavaType* @return*/public static String objectToJson(Object object, JavaType javaType){try {return objectMapper.writerFor(javaType).writeValueAsString(object);} catch (JsonProcessingException e) {throw new RuntimeException(e);}}/*** 普通对象转输出流* @param object 对象* @param out 输出流* @throws IOException*/public static void objectToPrintStream(Object object, OutputStream out) throws IOException {JsonGenerator generator = objectMapper.getFactory().createGenerator(out, JsonEncoding.UTF8);ObjectWriter writer = objectMapper.writer();writer.writeValue(generator, object);generator.flush();}
}
public class JacksonExample {public static void main(String[] args) throws IOException {String json = "{\n" +"    \"name\": \"name\",\n" +"    \"description\": \"description\",\n" +"    \"iName\": \"iName\",\n" +"    \"iDescription\": \"iDescription\"\n" +"}";JavaType javaType = JacksonUtil.getJavaType(Goods.class);Goods goods = JacksonUtil.stringToObject(json, javaType);Goods goods1 = JacksonUtil.stringToClass(json, Goods.class);System.out.println(JacksonUtil.objectToJson(goods, javaType));JacksonUtil.objectToPrintStream(goods1,System.out);}
}

在json的解析和转换成json的过程中,以对象的set/get方法作为属性的重要依据

image-20240128150445199

可以从下面的测试看出,get方法在解析和转换的过程中占主要地位

image-20240128151805876

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

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

相关文章

修复idea,eclipse ,clion控制台中文乱码

控制台乱码问题主要原因并不在编译器IDE身上&#xff0c;还主要是Windows的控制台默认编码问题。。。 Powershell&#xff0c;cmd等默认编码可能不是UTF-8&#xff0c;无需改动IDE的settings或者properties&#xff08;这治标不治本&#xff09;&#xff0c;直接让Windows系统…

小土堆pytorch学习笔记003 | 下载数据集dataset 及报错处理

目录 1、下载数据集 2、展示数据集里面的内容 3、DataLoader 的使用 例子&#xff1a; 结果展示&#xff1a; 1、下载数据集 # 数据集import torchvisiontrain_set torchvision.datasets.CIFAR10(root"./test10_dataset", trainTrue, downloadTrue) test_set …

uniapp,页面当有按钮的时候,可以做一个动态的效果

效果&#xff1a; 这个是当点着按钮的时候没有松开按钮的效果&#xff08;没有阴影&#xff09; 这个是当松开按钮的效果&#xff08;有阴影&#xff09; 原理讲解&#xff1a; 这段代码实现的业务逻辑是在一个Vue组件中控制“现金”按钮的阴影效果。具体来说&#xff0c;它通…

云上高可用系统-韧性设计模式

一、走近韧性设计模式 &#xff08;一&#xff09;基本概念 韧性设计模式是一系列在软件工程中用于提高系统韧性的设计原则、策略、实践和模式。韧性&#xff08;Resilience&#xff09;在这里指的是系统对于各种故障、异常和压力的抵抗能力&#xff0c;以及在遭受这些挑战后…

pnpm 源不对 Will retry in 10 seconds. 2 retries left.

现象 由于使用npm config set registry 切换淘宝源时&#xff0c;把地址打错了。 后面使用pnpm install 时出现 此时无论我怎么使用npm config set registry 或者pnpm config set registry 切回正确的源均没有效果。 解决 在其他用npm的项目运行一下npm i 再运行pnpm i 即…

经典目标检测YOLO系列(三)YOLOV3的复现(1)总体网络架构及前向处理过程

经典目标检测YOLO系列(三)YOLOV3的复现(1)总体网络架构及前向处理过程 和之前实现的YOLOv2一样&#xff0c;根据《YOLO目标检测》(ISBN:9787115627094)一书&#xff0c;在不脱离YOLOv3的大部分核心理念的前提下&#xff0c;重构一款较新的YOLOv3检测器&#xff0c;来对YOLOv3有…

时序预测 | MATLAB实现ICEEMDAN-SSA-GRU、ICEEMDAN-GRU、SSA-GRU、GRU时间序列预测对比

时序预测 | MATLAB实现ICEEMDAN-SSA-GRU、ICEEMDAN-GRU、SSA-GRU、GRU时间序列预测对比 目录 时序预测 | MATLAB实现ICEEMDAN-SSA-GRU、ICEEMDAN-GRU、SSA-GRU、GRU时间序列预测对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 时序预测 | MATLAB实现ICEEMDAN…

解密人工智能:探索机器学习奥秘

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 机器学习的定义二. 机器学习的发展历程三. 机器学习的原理四. 机器学习的分类…

ElevationStation:一款专为红队设计的权限提升测试工具

关于ElevationStation ElevationStation是一款专为红队设计的权限提升测试工具&#xff0c;在该工具的帮助下&#xff0c;广大红队研究人员和渗透测试人员可以轻松实现SYSTEM权限令牌的获取&#xff0c;并通过将目标账号提升至SYSTEM权限来测试目标操作系统的安全态势。 Elev…

【Spark系列3】RDD源码解析实战

本文主要讲 1、什么是RDD 2、RDD是如何从数据中构建 一、什么是RDD&#xff1f; RDD&#xff1a;弹性分布式数据集&#xff0c;Resillient Distributed Dataset的缩写。 个人理解&#xff1a;RDD是一个容错的、并行的数据结构&#xff0c;可以让用户显式的将数据存储到磁盘…

前端——CSS

目录 文章目录 前言 一.CSS简介 1.CSS选择器 2.CSS选择器语法 3.CSS样式引入 4.CSS 高级选择器 二.CSS样式 1.字体 ​编辑 2.文本 3. 背景 4.边框 5.边距 6.浮动 7.清除浮动 8.定位 9. 列表样式 10.伪类样式 三.盒子模型 四.CSS3新特性 1.边框 2.盒子阴影 …

12.从项目经理的生存哲学到适配器模式(Adapter Pattern)

如果这个世界没有了项目经理&#xff0c;事情的发展可能并不会如同想象中一样美好&#xff0c;相反&#xff0c;对于开发人员来说可能是噩梦的开始。 比如&#xff1a; 客户因为几个需求的具体实现大发雷霆&#xff0c;甚至开始恶语相向&#xff0c;一通含ma量极高的“斯伯坦语…

自然语言处理:transfomer架构

介绍 transfomer是自然语言处理中的一个重要神经网络结构&#xff0c;算是在传统RNN和LSTM上的一个升级&#xff0c;接下来让我们来看看它有处理语言序列上有哪些特殊之处 模型整体架构 原论文中模型的整体架构如下&#xff0c;接下来我们将层层解析各层的作用和代码实现 该…

3d模型怎么分辨材质?--模大狮模型网

在3D模型中&#xff0c;通常可以通过以下几种方式来分辨材质&#xff1a; 视觉检查&#xff1a;在3D渲染视图或预览窗口中&#xff0c;您可以直接观察模型的外观来区分不同的材质。不同的材质可能具有不同的颜色、纹理、反射率等特征&#xff0c;因此通过直观的视觉检查&#x…

LV老板重夺全球首富 再次超过马斯克;新东方安徽总部大厦启用;中国与泰国签署互免签证协定

今日精选 • LV老板重夺全球首富 再次超过马斯克• 新东方安徽总部大厦启用• 中国与泰国签署互免签证协定 投融资与企业动态 • ​​传Temu将于3月在美国上线半托管业务• 国内数字支付解决方案提供商 “连连数字” 估值150亿&#xff0c;即将IPO• 滴滴与宁德时代宣布成立…

深度强化学习(王树森)笔记05

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

安全防御{第三次作业(在第二次作业上添加点需求)}

目录 需求&#xff1a; 拓扑图&#xff1a; 注意&#xff1a;先打开防火墙web界面&#xff0c;在此不做演示 1.要求一&#xff1a;&#xff0c;生产区在工作时间内可以访问服务器区&#xff0c;仅可以访问http服务器 2.要求二&#xff1a;办公区全天可以访问服务器区&#…

BGP:03 BGP路由

这是实验拓扑&#xff0c;IBGP 利用环回口建立邻居&#xff0c;IGP 协议为 OSPF&#xff0c; EBGP 通过物理接口建立邻居 基本配置&#xff1a; R1: sys sysname R1 int loop 0 ip add 1.1.1.1 24 int g0/0/0 ip add 192.168.12.1 24 qR2: sys sysname R2 int loop 0 ip ad…

JCEF学习

JCEF重要概念 CEF CEF&#xff0c;全称Chromium Embedded Framework &#xff0c;它是基于Google Chromium的开源项目&#xff0c;它的目标是能够向第三方程序添加WEB浏览器功能&#xff0c;以及可以使用HTML、CSS和JS渲染界面。 CEF框架是由Marshall Greenblatt 在 2008 年创…

第17节-高质量简历写作求职通关-投递反馈

&#xff08;点击即可收听&#xff09; 投递跟进和感谢信 如果对一家公司特别心仪&#xff0c;但是投递简历后一直得不到回复怎么办&#xff1f; 面试之后觉得自己没有表现好怎么办&#xff1f; 面试完几天了&#xff0c;依然没有得到回应怎么办&#xff1f; 这个时候你需要写一…