当前位置: 首页 > news >正文

从 0 到 1 认识 Spring MVC:核心思想与基本用法(上)

文章目录

    • 📕1. 什么是Spring Web MVC
        • ✏️1.1 MVC 定义
        • ✏️1.2 什么是Spring MVC
    • 📕2. 建立连接
        • ✏️2.1 @RequestMapping 注解介绍
        • ✏️2.2 @RequestMapping 使⽤
        • ✏️2.3 @RequestMapping 是 GET 还是 POST 请求?
    • 📕3. 请求
        • ✏️3.1 传递单个参数
        • ✏️3.2 传递多个参数
        • ✏️3.3 传递对象​
        • ✏️3.4 后端参数重命名
        • ✏️3.5 传递数组
        • ✏️3.6 传递集合
        • ✏️3.7 传递JSON数据​
        • ✏️3.8 获取URL中参数@PathVariable ​
        • ✏️3.9 上传文件@RequestPart ​
        • ✏️3.10 获取Header

📕1. 什么是Spring Web MVC

官⽅对于 Spring MVC 的描述是这样的:

Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC”, comes from the name of its source module (spring-webmvc)引用来自

翻译为中⽂:
Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为"Spring MVC"

从上述定义我们可以得出⼀个信息: Spring Web MVC 是⼀个 Web 框架。简称之为: Spring MVC

✏️1.1 MVC 定义

MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构设计模式,它把软件系统分为模型、视图和控制器三个基本部分

在这里插入图片描述
View(视图) : 指在应⽤程序中专⻔⽤来与浏览器进⾏交互,展⽰数据的资源。

Model(模型): 是应⽤程序的主体部分,⽤来处理程序中数据逻辑的部分。

Controller(控制器): 可以理解为⼀个分发器,⽤来决定对于视图发来的请求,需要⽤哪⼀个模型
来处理,以及处理完后需要跳回到哪⼀个视图。即⽤来连接视图和模型。

🌰 举个例子:

当我们去饭店吃饭时,客⼾进店之后, 服务员来接待客⼾点餐, 客⼾点完餐之后, 把客⼾菜单交给前厅, 前厅根据客⼾菜单给后厨下达命令. 后厨负责做饭, 做完之后, 再根据菜单告诉服务员, 这是X号餐桌客⼈的饭.

在这个过程中:

服务员就是View(视图), 负责接待客⼾, 帮助客⼾点餐, 以及给顾客端饭

前厅就是Controller(控制器), 根据⽤⼾的点餐情况, 来选择给哪个后厨下达命令.

后厨就是Model(模型), 根据前厅的要求来完成客⼾的⽤餐需求

✏️1.2 什么是Spring MVC

MVC 是⼀种架构设计模式,也是⼀种思想,⽽ Spring MVC 是对 MVC 思想的具体实现。除此之外,Spring MVC还是⼀个Web框架。

总结来说,Spring MVC 是⼀个实现了 MVC 模式的 Web 框架。

其实, Spring MVC 我们在前⾯已经⽤过了, 在创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架
其实就是 Spring MVC 框架:

在这里插入图片描述

学习Spring MVC,重点也就是学习如何通过浏览器和⽤⼾程序进⾏交互。主要分以下三个⽅⾯:

  1. 建立连接:将⽤户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调⽤到我们的Spring 程序。
  2. 请求:⽤⼾请求的时候会带⼀些参数,在程序中要想办法获取到参数, 所以请求这块主要是 获取参数的功能
  3. 响应:执⾏了业务逻辑之后,要把程序执⾏的结果返回给⽤⼾, 也就是响应

📕2. 建立连接

在 Spring MVC 中使⽤ @RequestMapping 来实现 URL 路由映射 ,也就是浏览器连接程序的作⽤。

创建⼀个 UserController 类,实现⽤⼾通过浏览器和程序的交互,具体实现代码如下:

@RestController
public class Hello {@RequestMapping("/sayHi")public String hello(){return "hello,Spring MVC";}
}

接下来访问: http://127.0.0.1:8080/sayHi, 就可以看到程序返回的数据了

在这里插入图片描述

✏️2.1 @RequestMapping 注解介绍

@RequestMapping 是 Spring Web MVC 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的路由映射的。表⽰服务收到请求时,路径为 /sayHi 的请求就会调⽤ sayHi 这个⽅法的代码。

路由映射 : 当用户访问⼀个 URL 时, 将用户的请求对应到程序中某个类的某个⽅法的过程就叫路由映射。

既然 @RequestMapping 已经可以达到我们的⽬的了, 我们为什么还要加 @RestController呢?
我们把 @RestController 去掉, 再来访问⼀次:
在这里插入图片描述
可以看到, 程序报了404, 找不到该⻚⾯。这就是 @RestController 起到的作⽤。⼀个项⽬中, 会有很多类, 每个类可能有很多的⽅法, Spring程序怎么知道要执⾏哪个⽅法呢?Spring会对所有的类进⾏扫描, 如果类加了注解@RestController, Spring才会去看这个类⾥⾯的⽅法有没有加 @RequestMapping 这个注解, 当然@RestController的作⽤不⽌这⼀点,

✏️2.2 @RequestMapping 使⽤

@RequestMapping 既可修饰类,也可以修饰⽅法 ,当修饰类和⽅法时,访问的地址是类路径 + ⽅法路径.

@RequestMapping标识⼀个类:设置映射请求的请求路径的初始信息
@RequestMapping标识⼀个⽅法:设置映射请求请求路径的具体信息

@RestController
@RequestMapping("/user")
public class Hello {@RequestMapping("/sayHi")public String hello(){return "hello,Spring MVC";}
}

访问地址:http://127.0.0.1:8080/user/sayHi

在这里插入图片描述
⚠️注意:@RequestMapping 的URL 路径最前⾯加不加 / (斜杠)都可以, Spring程序启动时, 会进⾏判断, 如果
前⾯没有加 / , Spring会拼接上⼀个 /,通常情况下, 我们加上 /。

✏️2.3 @RequestMapping 是 GET 还是 POST 请求?

结论:@RequestMapping 既⽀持Get请求,⼜⽀持Post请求。同理,也⽀持其他的请求⽅式。

我们可以手动设置GET/POST⽅法类型

@RestController
@RequestMapping("/user")
public class Hello {//手动设置post请求@RequestMapping(value="/post", method = RequestMethod.POST)public String postHello(){return "hello,post";}//手动设置get请求@RequestMapping(value = "/get",method = RequestMethod.GET)public String getHello(){return "hello,post";}
}

📕3. 请求

✏️3.1 传递单个参数

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

@RestController
@RequestMapping("/param")
public class Hello {@RequestMapping("/m1")public String m1(String name){return "传递参数name:"+name;}}//咱们使用浏览器发送请求并传参 http://127.0.0.1:8080/param/m1?name=spring​

在这里插入图片描述

Spring MVC 会根据方法的参数名, 找到对应的参数, 赋值给方法​
在这里插入图片描述
如果参数不一致, 是获取不到参数的.​
比如请求URL: http://127.0.0.1:8080/param/m1?name1=spring​
在这里插入图片描述

⚠️注意事项: 使用基本类型来接收参数时,参数必须传(除boolean类型),否则会报500错误​。类型不匹配时, 会报400错误。

@RestController
@RequestMapping("/param")
public class Hello {@RequestMapping("/m1")public String m1(int age){return "传递参数age:"+age;}}

1.不传参数时
在这里插入图片描述
2.传递参数类型不匹配
在这里插入图片描述
对于包装类型,如果不传对应参数,Spring 接收到的数据则为null​。所以企业开发中,对于参数可能为空的数据,建议使用包装类型。

✏️3.2 传递多个参数

如何接收多个参数呢? 和接收单个参数⼀样,直接使⽤⽅法的参数接收即可,使⽤多个形参。

@RequestMapping("/m2")public String m2(String name,String password){return "name:"+name+"password:"+password;}
//使用浏览器发送请求并传参: http://127.0.0.1:8080/param/m2?name=zhangsan&password=123456​

在这里插入图片描述
可以看到, 后端程序正确拿到了name和password参数的值​
在这里插入图片描述
当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置是不影响后 端获取参数的结果. ​

✏️3.3 传递对象​

如果参数比较多时, 方法声明就需要有很多形参. 并且后续每次新增一个参数, 也需要修改方法声明.​ 我们不妨把这些参数封装为一个对象.​

Spring MVC 也可以自动实现对象参数的赋值,比如 Person 对象:​

package xulong.com;public class Student {private int id;private String name;private String password;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "Student{" +"id=" + id +", name='" + name + '\'' +", password='" + password + '\'' +'}';}
}

传递对象代码实现:

@RequestMapping("/m3")public String m3(Student student){return student.toString();}
//使用浏览器发送请求并传参: http://127.0.0.1:8080/param/m3?id=5&name=zhangsan&password=123456​

在这里插入图片描述
可以看到, 后端程序正确拿到了Person对象里各个属性的值​

在这里插入图片描述
Spring 会根据参数名称自动绑定到对象的各个属性上, 如果某个属性未传递, 则赋值为null(基本类型则 赋值为默认初识值, 比如int类型的属性, 会被赋值为0)​

✏️3.4 后端参数重命名

某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不一致,比如前端传递了一个 time 给后端,而后端是使用 createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现 这种情况,我们就可以使用@RequestParam 来重命名前后端的参数值. ​

@RequestMapping("/m4")public String m4(@RequestParam("time") String createTime){return "createTime:"+createTime;}//使用浏览器发送请求并传参: http://127.0.0.1:8080/param/m4?time=2023-09-12

在这里插入图片描述

如果浏览器使用createtime进行参数传递呢?​
访问URL: http://127.0.0.1:8080/param/m4?createtime=2023-09-12​
在这里插入图片描述

可以得出结论:

  1. 使用@RequestParam 进行参数重命名时, 请求参数只能和@RequestParam 声明的名称一 致, 才能进行参数绑定和赋值.​
  2. 使用@RequestParam 进行参数重命名时, 参数就变成了必传参数. ​

非必传参数设置​

如果我们的实际业务前端的参数是一个非必传的参数, 针对上述问题, 如何解决呢?​

先来了解下参数必传的原因, 我们查看 @RequestParam 注解的实现细节就可以发现端倪,注解 实现如下: ​
在这里插入图片描述
可以看到required 的默认值为true, 表示含义就是: 该注解修饰的参数默认为必传​

既然如此, 我们可以通过设置 @RequestParam 中的 required=false 来避免不传递时报错, 具体实现如下: ​

@RequestMapping("/m4")public String m4(@RequestParam(value = "time",required = false) String createTime){return "createTime:"+createTime;}
//可以看到, 添加required=false之后, time前面也加了key, 变成了 value = "time"
//注解属性赋值时, 没有指明key的话, 默认为value属性.​
//如果需要有多个属性进行赋值时, 需要写上key​
✏️3.5 传递数组

Spring MVC 可以自动绑定数组参数的赋值​

@RequestMapping("/m5")public String m5(String[] arrayParam){return Arrays.toString(arrayParam);}

这次让我们使用apifox发送请求

在这里插入图片描述

✏️3.6 传递集合

集合参数:和数组类似, 同一个请求参数名有为多个, 且需要使用 @RequestParam 绑定参数关系​

默认情况下,请求中参数名相同的多个值,是封装到数组. 如果要封装到集合,要使用@RequestParam 绑定参数关系

@RequestMapping("/m6")public String m6(@RequestParam List<String> listParam){return listParam.toString();}

在这里插入图片描述

如果不加@RequestParam,前端会报500错误。
在这里插入图片描述
在这里插入图片描述

✏️3.7 传递JSON数据​

JSON:JavaScript Object Notation 【JavaScript 对象表示法】​

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

JSON的语法

  1. 数据在键值对(Key/Value) 中
  2. 数据由逗号 , 分隔
  3. 对象用 {} 表示​
  4. 数组用[] 表示​
  5. 值可以为对象, 也可以为数组, 数组中可以包含多个对象​

JSON的两种结构​

  1. 对象: 大括号 {} 保存的对象是一个无序的键值对集合. 一个对象以左括号 { 开始, 右括号 } 结束。每个"键"后跟一个冒号 : ,键值对使用逗号, 分隔​
  2. 数组: 中括号 [] 保存的数组是值(value)的有序集合. 一个数组以左中括号[ 开始, 右中括 号] 结束,值之间使用逗号 , 分隔。​

在这里插入图片描述
在线JSON格式化校验工具

JSON字符串和Java对象互转​

public static void main(String[] args) throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();Student student = new Student();student.setId(1);student.setName("zhuxulong");student.setPassword("123456");String s = objectMapper.writeValueAsString(student);System.out.println(s);Student student1 = objectMapper.readValue("{\"id\":1,\"name\":\"zhuxulong\",\"password\":\"123456\"}", Student.class);System.out.println(student1.toString());}

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

  1. writeValueAsString: 把对象转为JSON字符串​
  2. readValue: 把字符串转为对象​

传递JSON对象​

接收JSON对象, 需要使用@RequestBody 注解(RequestBody: 请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须在写在请求正 文中)

@RequestMapping("/m7")public String m7(@RequestBody Student student){return student.toString();}

在这里插入图片描述

如果去除掉@RequestBody
在这里插入图片描述
后端未能成功给Person对象赋值.​

✏️3.8 获取URL中参数@PathVariable ​

path variable: 路径变量​。和字面表达的意思一样, 这个注解主要作用在请求URL路径上的数据绑定​。(默认传递参数写在URL上,SpringMVC就可以获取到​)

@RequestMapping("/m8/{id}/{name}")public String m8(@PathVariable Integer id ,@PathVariable  String name){return "id:"+id+"name:"+name;}

在这里插入图片描述
参数对应关系如下: ​

在这里插入图片描述

  1. 如果方法参数名称和需要绑定的URL中的变量名称一致时, 可以简写, 不用给@PathVariable的属性赋 值, 如上述例子中的id变量​
  2. 如果方法参数名称和需要绑定的URL中的变量名称不一致时, 需要@PathVariable的属性value赋值, 如上述例子中的userName变量.​
✏️3.9 上传文件@RequestPart ​

@RequestPart 是 Spring MVC 中用于接收 HTTP 请求中包含的复杂类型数据(如文件、JSON 对象等)的注解,通常用于处理 multipart/form-data 类型的请求。

@PostMapping("/upload")
public String uploadFile(@RequestPart("file")  MultipartFile file) {if (!file.isEmpty()) {try {// 获取原始文件名String fileName = file.getOriginalFilename();// 保存文件到指定路径file.transferTo(new File("upload/" + fileName));return "文件上传成功";} catch (Exception e) {return "文件上传失败: " + e.getMessage();}}return "请选择要上传的文件";
}

MultipartFile是什么?
在 Spring 框架中,MultipartFile 是一个接口,主要用于处理 HTTP 请求中的文件上传操作。它封装了上传文件的相关信息和操作方法,是 Spring MVC 中处理文件上传的核心组件。

在这里插入图片描述

✏️3.10 获取Header

传统获取Header

@RequestMapping("/m9")public String m9(HttpServletRequest request){return request.getHeader("User-Agent");}

在这里插入图片描述

简洁获取Header

@RequestMapping("/m10")public String m10(@RequestHeader("User-Agent")String userAgent){return userAgent;}

在这里插入图片描述

http://www.dtcms.com/a/310190.html

相关文章:

  • CIU32L030=CW32L010 PIN=PIN免费送样,开发板
  • 【论文学习】KAG论文翻译
  • 计算机基础速通--数据结构·线性表应用
  • RA4M2_MINI驱动OLED(1)----驱动OLED
  • LangChain框架入门04:10分钟优雅接入主流大模型
  • 智能Agent场景实战指南 Day 28:Agent成本控制与商业模式
  • 常见框架漏洞
  • dify
  • SSL 剥离漏洞
  • vue2实现类似chatgpt和deepseek的AI对话流打字机效果,实现多模型同时对话
  • OpenCV-python小玩意2 摄像头预览时画线以及line的用法
  • Vue 引入字体文件YouSheBiaoTiHei
  • VMware 下 Ubuntu 操作系统下载与安装指南
  • 前沿智能推荐算法:基于多模态图神经网络的隐私保护推荐系统
  • 学习笔记:原子操作与锁以及share_ptr的c++实现
  • 调试 Rust 生成的 WebAssembly
  • OSPF综合实验报告册
  • 1 前言:什么是 CICD 为什么要学 CICD
  • vue打包后如何在本地运行?
  • sqli-labs:Less-17关卡详细解析
  • 数据结构:在链表中查找(Searching in a Linked List)
  • PyTorch分布式训练深度指南
  • Unity 打包程序在大屏上显示的问题、分辨率问题、UI适配问题、字体模糊不清问题
  • androidstudio调试apt
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博评论数据可视化分析-用户评论词云图实现
  • Apple基础(Xcode仨-Singxob)
  • 从零到一:构建基于本地LLM和向量数据库的法律智能问答系统(win11本地搭建)
  • 【C++进阶】一文吃透静态绑定、动态绑定与多态底层机制(含虚函数、vptr、thunk、RTTI)
  • 改进PSO算法!新自组织分层粒子群优化算法,具有变化的时间变化加速系数,附完整代码
  • 交通拥挤识别准确率↑32%:陌讯时空特征融合算法实战解析