Spring【Again】——复杂POJO的绑定

news2024/12/23 14:19:11

简单介绍:

Again系列是将之前的内容我认为做的不好的地方或者是理解不到位的地方再来一次,加深记忆或者改错。我们就在来复习一下之前我们说过的复杂类型的数据绑定。

先来复习一下简单数据绑定:

简单数据绑定就是我们在传递参数的时候,传递的参数数量很少,数据类型单一,基本就是一两个的基本数据类型的时候才会用到,我们举个例子:

做一个简单的案例,首先我们创建一个空的项目,然后通过发送一个带有参数的请求,然后在Controller中接受这个参数的案例来介绍简单的数据绑定需要做什么:

创建一个Controller:

package com.Spring.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class UserController {
    @GetMapping
    public String select(String username){
        System.out.println(username);
        return username;
    }
}

这是一个接受请求参数的Controller,参数名叫做username,类型是String。当请求成功之后会将请求中的参数返回到请求端,并且在控制台上打印。

然后我们发送一个请求:

 我们的请求参数是张三,那么我们看到返回的值肯定也是张三,并且在控制台打印的就是张三,简单的数据绑定的格式和方式都很简单。

这种简单的方式适用于参数很少,一般也就一两个,并且类型简单的数据。如果是多个数据,我们一般会将它绑定到Java类上,这种方式叫做POJO绑定:

POJO绑定:

我们先创建一个封装数据的POJO类:

package com.Spring.pojo;

import lombok.Data;

@Data
public class user {
    private String name;
    private String password;
}

然后是发送请求的Controller 

//    POJO绑定
    @GetMapping("/ByUser")
    public String selectUser(user user){
        System.out.println(user.toString());
        return user.toString();
    }

我接下来写的所有的controller都会只写方法体,如果想要自己验证,可以随便粘贴放在类中,然后通过映射路径访问即可。

然后我们请求一下POJO绑定的路径:

这里还是注意一下我们请求的时候的参数,参数名要和类中的属性名一样才能被接受,如果参数名和属性名不一样,需要通过属性进行指定,否则无法自动接收。

核心思想: 

其实在一开始的时候,我们就要对这个参数有一个明确的认知,这个参数是什么,多个参数之间的关系是什么。对于前端浏览器来说,多个参数时间是松散的,可以是没有关系的,可以是单一的,对于前端来说,这个参数的格式对他们来说并不重要,只需要输入参数,然后发送到后端的controller就可以了,那么后端如何处理这个参数是我们要关心的事情,比如这个参数是什么类型,参数名是什么,参数要如何封装。

在现阶段,我们用来接收参数的对象,也就是这个东西:

这个方法中的参数user,我们就可以暂时先不把他理解成一个对象,理解成一个盒子,一个用来存放多个属性值的盒子,这个属性名和前端保持一致就可以了,这就是一个盒子,放了很多的数据,或者说多个数据存放到了一个盒子里面,为什么这个盒子是Java类,因为我们用的是Java做后端语言,操作Java类肯定是更方便一些。如果用别的语言肯定就是其他格式的盒子。 

带着这种想法,我们剩下的就是怎么往盒子里面放数据了,其实格式非常的简单,因为我们现在学的前端的那些表单控件无法做到一次传递多个数据,也就是一个input标签只能传递一个数据,那么我们在传递的时候就可以通过精确定位某一个数据的形式,可丁可卯的把数据放到盒子里。

复杂数据类型绑定——数组:

数组类型的绑定适用于多个属性名相同,但是属性值不相同的,比如我们在使用多选功能的时候,我们一次性选择了多个,我们又想把多个数据存储在一起,那么就需要后台绑定的时候,将前端传递进来的数据绑定成数组,基本步骤如下:

1、定义一个前端表单,向后端传递多个参数名一样但是参数值不一样的数据。使用我们的多选框是最适合不过的了:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<form action="http://localhost:8080/users/ByList" method="post">
    <table>
        <tr>
            <th>选择</th> <th>学科</th>
        </tr>
        <tr>
            <th><input type="checkbox" name="args" value="1"></th> <th>数学</th>
        </tr>
        <tr>
            <th><input type="checkbox" name="args" value="2"></th> <th>语文</th>
        </tr>
        <tr>
            <th><input type="checkbox" name="args" value="3"></th> <th>英语</th>
        </tr>
        <tr>
            <td><input type="submit" value="提交"></td>
        </tr>
    </table>
</form>
</body>
</html>

然后就是一个简单的只有一个复选框的表单,我们需要注意三个地方,第一个就是表单的提交路径,这个路径对应我们controller的映射地址,这个地址写错了你后面的controller铁定是接收不到数据。第二个就是表单的name,这个值对应我们controller中的方法的形参的变量名。最后就是value,这个值就是我们选中后将要填充进数组中的值,最后我们选中了几,就会看到他输出的是几,然后我们就来看后台的controller是如何写的:

//    List数组绑定
    @PostMapping("/ByList")
    public Integer[] selectList(Integer [] args){
        System.out.println(Arrays.toString(args));
        return args;
    }

其实跟之前一样的,只不过注意这个地方方法的形参的参数要和前端的表单中的input标签中的name的属性值保持一致,然后因为我们的表单提交是使用post方式,所以方法使用@PostMapping注解标注。

然后我们先启动程序,然后提交标签:

我们先全选,然后提交:

最后一行已经显示了我们选择的value值,然后我们少选一个:

按照我们的猜想,这次输出的数组中不会存在2:

 合理,跟我们的猜想是一样,说明我们之前做的对的。

 图示看起来非常的简单,在实际操作的时候也确实是很简单,毕竟数组就是一个可变的盒子,多一个少一个都无所谓,甚至没有都可以。

泛型为基本数据类型的绑定和之前的数组的绑定的格式是基本差不多的,唯一的区别就是在controller上作为参数接收的时候,需要加上一个@RequestParam,否则会导致一个报错,待会我们会演示这个报错并说明一下这个报错是如何形成的。

先给看一下后台的controller是如何写的,前端的页面是没有发生改变的,然后我们启动程序,向这个controller中发送一些参数:

 

我们选择跟之前一样的表单数据,然后观察他的返回值:

跟之前是一样的,也就是说格式不变,只不过参数的类型改变,以及添加了一个注释,那么这个注释如果不加会怎么样的?

 

现在我们删除这个注释,然后重启服务器,再次发送请求:

 在控制台爆出了这么一个错误,这个错误的意思是找不到接口java.util.List的主构造函数或单个唯一构造函数,找不到构造函数,那么他是想干什么才会用到这个构造函数呢?他想创建一个List对象,但是接口不能直接创建对象,所以我们要用这个注解表示我们创建的其实不是List的集合,而是将我们接受到的参数作为一组数据存储到集合中,这个注解的作用就是指明我们传递进来的数据是要以何种类型存储。

复杂POJO绑定:

还记得之前我们说过的,对于数据绑定来说,我们的对象就是一个盒子,那么既然他是一个盒子,那么盒子就可以套盒子,那么有趣的地方就来了。所谓的复杂POJO是和简单POJO对比来的,简单POJO的属性都是简单数据类型,String虽然是对象,但是此处也暂时当简单数据类型。那么复杂POJO的属性可以是对象,可以是数组,可以是集合,可以是Map,可以是集合里面套数组,可以是集合里面套对象,可以是集合里面套对象套数组,可以是……

简单来说,复杂POJO的复杂就体现在我们现在的盒子不是打开就能看见数据了,是打开之后是盒子,盒子再打开才是数据,甚至盒子打开之后还是盒子,盒子打开之后开始盒子,然后才是数据,那就自己玩去吧。

我们就说集中常见的:

POJO属性是对象的情况:

我们先学思想,然后看图,最后看代码实现,如果能不看到代码就做出来,那就是学会了:

现在有一个类叫做A,然后A里面包含一个属性,这个属性是一个对象,叫做B,就像这样:

 这是可以的吧,我的属性是一个对象,然后这个对象有自己的属性,那么我们怎么访问这个属性呢?

调用呗~回归到最基础的Java语法了,怎么调用啊?

A.B.name呗,是不是?如果忘记了我们就用代码写一写:

 

 这是B他的属性都用基本数据类型,然后我们创建A:

为了做对比,我们在A里面除了B属性之外,再添加一个简单数据类型的属性,然后我怎么通过A获取B里面的数据啊?直接调用方法就行了:

我可以这么写吧,如果这里不理解,建议回去复习一下Java的语法,为什么要说到这个呢,因为前段传入数据的方式也是这么来的,只不过我们这里是调用方法,getB啊,getName啊,前端更方便,直接调用属性就行了:

注意看input标签的name属性,就直接用你要绑定的类的属性去调用就可以了,比如我的b属性是一个对象,b对象中包含name属性和age属性,那么就直接写“b.name”就可以将数据绑定到B属性的name属性上,然后我们看返回值:

 

是不是跟我们写的一样,id是普通数据类型, b是复杂数据类型,也就是对象,然后输出的格式就像上面是一样的。然后来看我们controller是怎么写的。

 

还有一个重要的地方就是,我们所有的数据绑定的这些写法,都是写在前端的,对我们的后端来说,Java类就是Java类,我们直接拿来用就可以了,这就是为什么我要用数据绑定的方式将数据放在盒子里,因为我们的Java操作盒子非常的简单。 

 其他方式:

其实道理都是一样的,其他的无非就是属性是LIst还是属性是Map,我把这两个的图画出来,然后简单的说一下,但是代码就不写了,如果看完之后还是不会写的,评论或者私信我,我单独发给你。

属性为List的,List的泛型是对象类型的:

通过数组的下标定位到集合中的元素,然后通过集合的元素调用对象的属性

 属性为Map类型,Map值的泛型是B类型:

Map类型通过键查找对应的值,所以在插入的时候通知键查找到最对应的值,然后值包含多个属性,通过值找到对应的属性,完成赋值

 

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

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

相关文章

京东jd商品详情API接口(item_get-根据ID取商品详情)代码封装

item_get-根据ID取商品详情接口 通过代码封装该接口可以拿到商品标题&#xff0c;商品价格&#xff0c;商品促销信息&#xff0c;商品优惠价&#xff0c;商品库存&#xff0c;sku属性&#xff0c;商品图片&#xff0c;desc图片&#xff0c;desc描述&#xff0c;sku图片&#xf…

文件上传下载系列——大文件分片上传

文章目录 概述实现步骤&#xff1a;应用场景 代码实操&#xff1a;前端&#xff1a;文件切片&#xff1a;分片上传&#xff1a; 后端&#xff1a;校验和保存&#xff1a;合并文件片段&#xff1a;完成上传&#xff1a; 总结优点&#xff1a;缺点&#xff1a; 升华 概述 文件分片…

spring cache和SpEL表达式

spring cache的 CachePut如果方法体内容变了,缓存还有效吗 当使用CachePut注解时&#xff0c;其目的是更新缓存&#xff0c;即在方法执行完毕后将返回结果加入缓存中。如果方法体内容发生变化&#xff0c;则更新后的结果会被加入缓存中&#xff0c;而缓存中原来的数据会被替换…

ORACLE 新闻速递 ORACLE 23C 免费提供给开发者 为什么???

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群&#xff08;共…

利用AI将脑信号解码为神经义肢控制

机器学习和人工智能的快速发展&#xff0c;它们已经产生了一系列能够学习大量数据之间复杂非线性关系的神经网络模型。深度学习算法在各种应用中取得了巨大的成功&#xff0c;包括计算机视觉、自然语言处理和机器人类等。最近&#xff0c;神经网络的中一项引人注目的应用是通过…

B 站构建实时数据湖的探索和实践

摘要&#xff1a;本文整理自 bilibili 大数据实时团队资深开发工程师周晖栋&#xff0c;在 Flink Forward Asia 2022 实时湖仓专场的分享。本篇内容主要分为四个部分&#xff1a; 1. 背景和痛点 2. 场景探索 3. 基建优化 4. 总结和展望 Tips&#xff1a;点击「阅读原文」查看原…

VMware之esxcli命令

一、esxcli命令简介 esxcli命令是用于管理VMware ESXi主机的命令行实用程序。它允许管理员在主机上执行各种管理任务&#xff0c;如配置网络设置、存储、虚拟机等。实际上我们在控制台的所有操作最终都会转换为命令在后台执行。以下是一些常见的esxcli命令&#xff1a; esxcli…

第三章 存储系统

1. 主存简单模型和寻址概念 存储器芯片的基本结构 寻址 2.存储器RAM 两种RAM的比较 DRAM的刷新 3.ROM(只读存储器) 为什么需要ROM&#xff1f; 因为RAM里面的数据容易丢失。 4.存储器基本概念 存储器的分类 性能指标 数据的宽度&#xff1a;在一个存储周期中存储的位数 层…

感烟探测器漂移补偿

3.8 慢速发展火灾响应性能 3.8.1 探测器的漂移补偿功能不应使探测器对慢速发展火灾的响应性能产生明显影响。 3.8.2 当无法用模拟烟气浓度缓慢增加的方法评估探测器对慢速发展火灾响应性能时&#xff0c;可以通过物理试验和模拟试验对电路和/或软件分析确定。 3.8.3 探测器评估…

丰富多彩 | Android 14 Beta 2 发布

作者 / Dave Burke, VP of Engineering Google I/O 的大幕已经拉开&#xff0c;我们也为大家带来了 Android 14 的第二个 Beta 版。我们在 Google I/O 上为大家准备了许多精彩的演讲&#xff0c;包括对 Android 14 许多新功能的详细介绍。这次发布的 Beta 2 聚焦相机和媒体、隐…

只要学会这些AI工具,一个人就是一家营销咨询公司

本教程收集于:AIGC从入门到精通教程 只要学会这些AI工具,一个人就是一家营销咨询公司 随着AI工具的不断涌现,您只需掌握市面上热门的AI工具,便可独自开展营销咨询公司。通过一系列AI工具,您可以为企业提供全案服务,收获丰厚回报。 例如,在协助一家美妆初创公司出海时,…

上下文工程:基于 Github Copilot 的实时能力分析与思考

上个月在计划为 AutoDev 添加多语言支持时候&#xff0c;发现 GitHub Copilot 的插件功能是语言无关的&#xff08;通过 plugin.xml 分析&#xff09;&#xff0c;便想研究一下它是如何使用 TreeSitter 的。可惜的是&#xff0c;直到最近才有空&#xff0c;研究一下它是如何实现…

印刷和喷绘过程中高精度油墨流量和压力的串级控制解决方案

摘要&#xff1a;针对现有技术在印刷或喷绘设备中油墨流量控制不准确&#xff0c;使得油墨粘稠度产生异常造成批量性质量方面的问题&#xff0c;本文提出了相应的串级控制解决方案&#xff0c;即通过双回路形式同时控制油墨的流量和压力。本解决方案不仅可以保证油墨最终流量的…

【C++ 入坑指南】(07)判断

文章目录 一、if 语句1. 单行格式 if 语句2. 多行格式 if 语句 二、三目运算符三、switch 语句四、算法题4.1 分段函数 判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&am…

C++ - 使用RBTree来封装Set与Map

前面的文章中我们简单的实现了一个红黑树&#xff0c;实现了它的插入的功能&#xff0c;在本文中我们来对其进行修改并构建Set与Map。 下面我们来从源码中截取一点有关Map与Set的代码&#xff1b; 可以看出&#xff0c;在STL30中构建Map与Set使用的是同一个红黑树模板&#xf…

开箱即用!AI模型库全新发布,一站式在线开发部署!

人工智能学习与实训社区飞桨AI Studio模型库全新升级&#xff01;支持模型创建、上传、托管并一键调用模型线上开发部署&#xff01; 飞桨AI Studio已接入飞桨生态特色模型库&#xff0c;全面覆盖模型领域&#xff0c;包含文心系列大模型、CV、NLP、语音、科学计算、量子计算等…

Linux常用命令——hwclock命令

在线Linux命令查询工具 hwclock 显示与设定硬件时钟 补充说明 hwclock命令是一个硬件时钟访问工具&#xff0c;它可以显示当前时间、设置硬件时钟的时间和设置硬件时钟为系统时间&#xff0c;也可设置系统时间为硬件时钟的时间。 在Linux中有硬件时钟与系统时钟等两种时钟。…

XR文字输入技术

VR/AR/MR&#xff08;统称为XR&#xff09;有望成为个人电脑、手机之后的下一代计算平台&#xff0c;元宇宙的硬件入口。 近年来XR发展迅猛&#xff0c;不仅可以应用于游戏、影视领域&#xff0c;还在军事、医疗、办公、教育等领域有巨大的发展前景。然而相比于XR强大的显示技…

IPWorks IPC .NET 2022.0.85 Crack

IPWorks IPC .NET一个组件库&#xff0c;用于通过命名管道向应用程序添加进程间通信 &#xff08;IPC&#xff09; 功能。包括客户端、服务器和外部进程执行组件&#xff0c;用于进程之间的简单对等通信。 最新的IPWorks IPC现已上市&#xff01;最新版本的 IPWorks IPC 具有现…

我用ChatGPT搞懂GPT技术原理,只问了30个问题,这是极致的学习体验!

自己前段时间写了一篇文章《问了ChatGPT 上百个问题后&#xff0c;我断定ChatGPT可以重塑学习范式&#xff01;》&#xff0c;讲了使用ChatGPT的感受&#xff0c;最近我开始学习GPT的技术原理&#xff0c;原因有三个&#xff1a; 1、工作中有可能要用到GPT&#xff0c;理解GPT的…