目录
🐳今日良言:少年负壮气,奋烈自有时
🐳一、Spring MVC的相关介绍
🐕1.Spring MVC的定义
🐕2.MVC 和 Spring MVC的关系
🐳二、Spring MVC的创建及使用
🐯1.Spring MVC项目创建
🐯2.Spring MVC相关注解介绍
🐯3.获取参数
🐳三、请求转发和请求重定向的区别
🐍1.请求转发
🐍2.请求重定向
🐍3.二者的区别
🐳今日良言:少年负壮气,奋烈自有时
🐳一、Spring MVC的相关介绍
🐕1.Spring MVC的定义
Sprintg MVC的定义:Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc),但它通常被称为“Spring MVC”。
要理解Spring MVC之前,首先需要了解一下什么是 MVC?
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。
Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据,控制⽤户输⼊,并向模型发送数据。
🐕2.MVC 和 Spring MVC的关系
在了解了MVC后,那么Spring MVC 和 MVC的关系是什么呢?
总结来说,MVC 是⼀种思想,⽽ Spring MVC 是对 MVC 思想的具体实现。
Spring MVC 是⼀个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。既然是 Web框架,那么当⽤户在浏览器中输⼊了 url 之后,我们的 Spring MVC 项⽬就可以感知到⽤户的请求。
🐳二、Spring MVC的创建及使用
🐯1.Spring MVC项目创建
🐯2.Spring MVC相关注解介绍
2.1@RequestMapping
在Spring MVC 中使用 该注解实现 URL 路由映射,也就是浏览器连接程序的作用。
路由映射:所谓的路由映射指的是,当⽤户访问⼀个 url 时,将⽤户的请求对应到程序中某个类 的某个⽅法的过程就叫路由映射
接下来,创建⼀个 UserController 类,实现⽤户到 Spring 程序的互联互通,具体实现代码如下:
@Controller
@ResponseBody // 返回非静态页面数据
public class Controller1 {
@RequestMapping("/index")
public Object getIndex() {
return "hello Spring MVC";
}
}
启动项目后,输入URL:127.0.0.1:8080/index
@RequestMapping 即可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类 + ⽅法。@RequestMapping 也可以直接修饰⽅法。
默认情况下是get请求。
那么,能不能指定GET或者POST 请求类型呢?
答案是可以的。
GET请求的三种写法:
1.@RequestMapping("/index")
2.@RequestMapping(value = "/exe1",method = RequestMethod.GET)
3.@GetMapping("/exe2")
POST请求的两种写法:
1.@RequestMapping(value = "/post1",method = RequestMethod.POST)
2.@PostMapping("/post2")
2.2@RequestBody
🐯3.获取参数
3.1传递单个参数并获取
在 Spring MVC 中可以直接⽤⽅法中的参数来实现传参,⽐如以下代码:@RequestMapping("/input") public String get(String name) { System.out.println("参数 name:"+name); return "ok"; }
此时,在对应的URL后跟上键值对,key是name,value随便值即可。
启动项目,输入URL:
此时查看控制台打印信息:
通过上述方法即可获取单个参数。
注:由于返回的是非静态页面的数据,因此,需要使用@RequestBody注解,否则会报错,如果需要返回的是静态页面,则不需要添加这个注解。
3.2传递对象
Spring MVC 可以⾃动实现参数对象的赋值,⽐如 Student对象:
@Data public class Student { private int id; private String name; private int age; }
传递对象代码如下:
@RequestMapping("/input") public String get(Student student) { System.out.println("对象中的 id:"+student.getId()); System.out.println("对象中的 name:"+student.getName()); System.out.println("对象中的 age:"+student.getAge()); return "ok"; }
启动项目,输入网址:
查看控制台打印信息:
如果查询字符串中没有该对象的属性,则获取到的属性是该属性类型的默认值,如int为0,boolean 是false。
3.3传递多个参数(非对象)
获取多个参数的代码如下:
@RequestMapping("/input") public String get(String name,String password) { System.out.println("参数中的 name:"+name); System.out.println("参数中的 password:"+password); return "ok"; }
启动项目,输入网址:
查看控制台打印信息:
当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置
是不影响后端获取参数的结果。
3.4后端参数重命名(后端参数映射)
某些特殊的情况下,前端传递的参数 key 和我们后端接收的 key 可以不⼀致,⽐如前端传递了⼀个 time 给后端,⽽后端⼜是有 createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现 这种情况,我们就可以使⽤ @RequestParam 来重命名前后端的参数值。后端参数重命名的代码如下:@RequestMapping("/input") public String get(@RequestParam("time")String creatime) { System.out.println("时间:"+creatime); return "ok"; }
启动项目,输入网址:
查看控制台打印信息:
3.5设置参数必传@RequestParam
在3.4的代码中,如果输入的URL的查询字符串中传递一个非time的参数,就会出现程序报错的情况,如下图:
@RequestMapping("/input")
public String get(@RequestParam(value = "time",required = false)String creatime) {
System.out.println("时间:"+creatime);
return "ok";
}
此时,再次传入非time参数,不会发生错误。
3.6@RequestBody 接收JSON对象
注意,这里并不是像3.2一样,在查询字符串中传入参数。
使用 Postman 构造JSON对象:
相关代码如下:
@RequestMapping("/input")
public Object get(Student student) {
return student;
}
启动项目,会发现即使输入了对象的属性,但是还是接收不到对象:
此时,需要使用注解@RequestBody
@RequestMapping("/input")
public Object get(@RequestBody Student student) {
return student;
}
启动项目,构造JSON对象,获取成功:
3.7获取URL中参数@PathVariable
后端代码如下:
@RequestMapping("/input/{name}/{password}")
public Object get(@PathVariable String name,@PathVariable String password) {
return "name:"+name+"password:"+password;
}
启动项目,输入URL:
需要注意,前端必须和 /input 后面的{name}和{password}一一对应,否则会报错:
当修改input后面的password为pwd后,此时启动项目会发现报错:
观察@PathVariable 源码会发现:
想要不报错,将这个参数的requred设置为false即可。
启动项目,输入URL:
注:
@PathVariable 获取的是 ?之前的参数
@RequestParam 获取的是 ? 之后的参数
3.8上传对象@RequestPart
后端代码:
@RequestMapping("/myupload")
public Object upload(@RequestPart("haiyang")MultipartFile file) {
// 要上传到的路径
File save = new File("D:\\Data\\haiyang.png");
try {
file.transferTo(save);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
通过Postman 上传文件:
此时观察D盘下的Data文件夹,会发现上传文件成功:
但是这种传输会导致一种问题,后面传输的文件会覆盖前面传输的文件,该如何解决这种问题呢?
只需要让用户上传的文件保存后的文件名不同即可,使用UUID(通用唯一符)生成全球唯一的标识符再拼接上用户上传的文件名的后缀名作为新文件名进行保存。
修改后的代码如下:
@RequestMapping("/myupload")
public Object upload(@RequestPart("haiyang")MultipartFile file) {
String fileName = UUID.randomUUID() + // 文件名
file.getOriginalFilename().substring( // 文件后缀
file.getOriginalFilename().lastIndexOf(".")
);
// 要上传到的路径
File save = new File("D:\\Data\\"+fileName);
try {
file.transferTo(save);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
此时,再次使用Postman上传文件,会发现每次提交的文件都会保存。
🐳三、请求转发和请求重定向的区别
🐍1.请求转发(forward)
请求转发的定义:请求转发是指在服务器端将用户请求转发到另一个URL,这个URL可以是同一个Web应用程序中的另一个Servlet或JSP页面,也可以是另一个Web应用程序中的URL。
相关代码:
@RestController
@RequestMapping("/test")
class Controller1{
@RequestMapping("/forward")
public Object getFw() {
return "forward:/index.html";
}
}
这里的 /index.html 的 / 表示去根路径下找这个index.html 文件。
在static 下创建一个静态页面 index.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的静态页面</title>
</head>
<body>
<h1>hello 这是静态页面</h1>
</body>
</html>
启动项目,输入URL:127.0.0.1:8080/test/forward
使用Fiddler 进行抓包:
会发现,对于客户端而言,只向服务器发送了一次请求。
🐍2.请求重定向(redirect)
请求重定向的定义:请求重定向是指服务器端接收到客户端的请求之后,会给客户端返回了一个临时响应头,这个临时响应头中记录了,客户端需要再次发送请求(重定向)的 URL 地址,客户端再收到了地址之后,会将请求发送到新的地址上。
相关代码:
@RequestMapping("/redirect")
public Object getRD() {
return "redirect:/index.html";
}
启动项目,输入URL:127.0.0.1:8080/test/redirect
使用Fiddler 进行抓包:
会发现,对于客户端而言,向服务器发送了两次请求。
🐍3.二者的区别
举一个简单的例子:
有一天,你跟妈妈说你想吃辣条,妈妈说:好,我去给你买。过了一会,妈妈买回辣条,然后交到你的手上,这个过程可以理解为:请求转发。
有一天,你跟妈妈说你想吃辣条,妈妈说:我给你钱,你自己去买。当你拿到钱后,你自己买到了辣条。这个过程可以理解为:请求重定向。
下面这幅图可以帮助理解。
假设你们学校的教务系统更换了网址,URL 由之前的/hello 更改为 /hello2。
forward 和 redirect 具体区别如下:
1. 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
2. 请求重定向地址发⽣变化,请求转发地址不发⽣变化。
3. 请求重定向与直接访问新地址效果⼀直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。