观前提示:本篇博客演示使用的 IDEA 版本为2021.3.3版本,使用的是Java8(又名jdk1.8)
电脑使用的操作系统版本为 Windows 10
目录
2. 选择 SpringBoot 项目, 选择合适的 jdk 版本, 设置创建项目源
4. 从基础 URL 中获取参数(不是从 URL 的参数部分获取参数)
2. 跳转地址: 请求转发(forward)和请求重定向(redirect)
前言
前面两篇博客介绍了 Spring 的 Bean 的作用域和生命周期, 本篇博客将开始介绍 Spring MVC 的常用注解以及用法
在认识 Spring MVC之前,先认识一下 Spring Boot
Spring Boot
Spring 的诞⽣是为了简化 Java 程序的开发的,⽽ Spring Boot 的诞⽣是为了简化 Spring 程序开发的。它是为了快速开发 Spring 框架⽽诞⽣的。
Spring MVC
Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称
(Spring-webmvc),但它通常被称为“Spring MVC"。
从上述定义我们可以得出两个关键信息:
1. Spring MVC 是⼀个 Web 框架。
2. Spring MVC 是基于 Servlet API 构建的。
然⽽要真正的理解什么是 Spring MVC?我们⾸先要搞清楚什么是 MVC?
1. MVC
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。
Model(模型)是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
View(视图)是应⽤程序中处理数据显示的部分。通常视图是依据模型数据创建的。
Controller(控制器)是应⽤程序中处理⽤户交互的部分。通常控制器负责从视图读取数据,控制⽤户输⼊,并向模型发送数据。
1.1 MVC 和 Spring MVC 之间的关系
MVC 是⼀种思想,⽽ Spring MVC 是对 MVC 思想的具体实现。
总结来说,Spring MVC 是⼀个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。既然是 Web框架,那么当⽤户在浏览器中输⼊了 url 之后,我们的
Spring MVC 项⽬就可以感知到⽤户的请求。
2. 创建 Spring MVC 项目
现在绝⼤部分的 Java 项⽬都是基于 Spring(或 Spring Boot)的,⽽ Spring 的核⼼就是 SpringMVC。也就是说 Spring MVC 是 Spring 框架的核⼼模块,
⽽ Spring Boot 是 Spring 的脚⼿架,因此我们可以推断出,现在市⾯上绝⼤部分的 Java 项⽬约等于 Spring MVC 项⽬。
在创建 Spring Boot 项⽬时,我们勾选的 Spring Web 框架其实就是 Spring MVC 框架,如下所示:
创建一个 SpringMVC 项目
1. new project
2. 选择 SpringBoot 项目, 选择合适的 jdk 版本, 设置创建项目源
3. 项目的参数
我选择 JDK 8 是因为我装的就是 JDK 8
4. 选择Spring Boot 版本, 添加项目依赖
在勾选的时候,可以注意看, Spring Web 下面有 Spring MVC, 这就是使用 Spring Boot 创建 Spring MVC
5. 设置项目名称和保存路径
6. 确保 idea 正常加载Spring Boot 项目
启动项目, 没有出现 debug, 并且控制台打印了启动所用的时间, 说明 Spring Boot项目已经创建好了
7. 删除无用文件(可删可不删)
这里面存储的是一些对我们帮助不大的文件
其中 .mvn目录 和 mvnw 文件以及 mvnw.cmd 文件, 是一个用来帮助在没有安装 Maven 的情况下运行 Maven 项目的脚本。
help.md
文件是 Spring Boot 项目的帮助文档,它包含了当前项目的基本信息、可用命令以及如何使用这些命令等重要内容。
是否删除看你个人选择,不做强制要求
是否删除看你个人选择,不做强制要求
是否删除看你个人选择,不做强制要求
8. Spring Boot 目录说明
3. SpringMVC 中的常用注解和用法
3.1 实现连接
@RequestMapping 是 Spring Web 应⽤程序中最常被⽤到的注解之⼀,它是⽤来注册接⼝的路由映射的。
先建立 com.example.demo.Controller, 在里面建立 UserController类
package com.example.demo.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller //让 Spring 框架启动时,加载
@ResponseBody //返回非页面数据
@RequestMapping("/user") // 路由器规则注册,此时是一级路由
public class UserController {
@RequestMapping("/hello") // 路由器规则注册,此时是二级路由,可以一直往下套,无限层
public String Hello() {
return "<h1>Hello,World<h1>";
}
}
运行程序,访问 http://localhost:8080/user/hello
此时完成了程序员的经典操作输出 Hello World
对于 @Controller 和 @ResponseBody 可以使用 @RestController 取代,因为点开 @RestController 的源码会发现,他有这两位的注解
@RequestMapping 支持 GET 和 POST
打开 Postman, 进行测试即可知道答案
@GetMapping 只支持 Get 请求
给 get 发送 POST 请求就会报错405
@PostMapping 只支持 Post 请求
给 POST 发送 Get 请求就会报错405
上面三个的测试代码
package com.example.demo.Controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user") // 路由器规则注册,此时是一级路由
public class UserController {
@RequestMapping("/hello") // 路由器规则注册,此时是二级路由,可以一直往下套,无限层
public String Hello() {
return "<h1>Hello,World<h1>";
}
@PostMapping("/post")
public String post() {
return "post";
}
@GetMapping("/get")
public String get() {
return "get";
}
}
3.2 获取参数
1. 获取单个参数
package com.example.demo.Controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping
public String name(String name){
return "hi " + name;
}
}
注意: url 里面的 name 必须和 idea 里面传参的 name 保持一致
获取多个参数
@RequestMapping("/name")
public String name(String name, String password) {
return "name: " + name + " " + "password: " + password;
}
在不输入name以及 password的情况下,默认是 null
2. 获取对象
获取对象之前需要先创建一个对象出来
新建 com.example.demo.enity ,再建一个 Userinfo 类
package com.example.demo.enity;
import lombok.Data;
@Data
public class Userinfo {
private int id;
private String name;
private String password;
private int age;
}
其中, @Data 是 lombok 他会帮我处理 get,set
@RequestMapping("/reg")
public Object reg(Userinfo userinfo){
System.out.println(userinfo);
return userinfo;
}
注意: 框架会实现自动的参数映射
3. 获取 JSON 对象
@RequestMapping("/reg2")
public Object reg2(@RequestBody Userinfo userinfo){
System.out.println(userinfo);
return userinfo;
}
继续使用 Postman
4. 从基础 URL 中获取参数(不是从 URL 的参数部分获取参数)
@PathVariable: 基础 URL 里面的参数(? 之前的参数)
@RequestParm: URL 参数部分的参数(? 之后的参数)
package com.example.demo.enity;
import lombok.Data;
@Data
public class Userinfo {
private int id;
private String name;
// private String password;
private String pwd;
private int age;
}
将 password 修改成 pwd
@RequestMapping("/reg3/{name}/{pwd}")
public Object reg3(@PathVariable String name, @PathVariable(required = false, name = "pwd") String password) {
return "name=" + name + " " + "password=" + password;
}
上述代码中,我们使用 @RequestMapping
注解将请求映射到 /reg3/{name}/{pwd}
路径上,并使用 @PathVariable
注解绑定 URL 路径变量到方法参数上。
具体来说,@PathVariable String name
表示将 URL 路径中的 {name}
变量映射到方法参数 name
上;而 @PathVariable(required = false, name = "pwd") String password
表示将 URL 路径中的 {pwd}
变量映射到方法参数 password
上。其中,required=false
表示 {pwd}
变量是可选的,如果请求 URL 中不包含该变量,则 password
参数的值为 null
;name="pwd"
表示将 {pwd}
变量与 password
方法参数名称进行映射,即使它们名称不匹配。
在方法体内部,我们使用字符串拼接的方式将 name
和 password
变量的值组合成一个响应字符串,并返回给客户端。
小结: 该方法的作用是根据传入的用户名和密码,在服务器端生成响应字符串并返回给客户端。如果请求 URL 中不包含密码变量,则返回的字符串中不包含密码信息。
5. 获取上传文件
@RequestMapping("/myupload")
public Object upload(@RequestPart("hero") MultipartFile file) {
File saveFile = new File("D:\\blogTest\\hero.jpg");
try {
file.transferTo(saveFile);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
使用 Postman 进行模拟
注意: 你要上传的图片和你要保存的图片不能再一个文件夹里面,因为看不出来区别,看不出来是因为有个缺陷
上面这段代码有个缺陷,就是你新上传的图片会覆盖上一张图片,这里面始终只有一张图片
@RequestMapping("/myupload")
public Object upload(@RequestPart("hero") MultipartFile file) {
String fileName = UUID.randomUUID() + // 文件名
file.getOriginalFilename().substring( // 文件后缀
file.getOriginalFilename().lastIndexOf("."));
File saveFile = new File("D:\\blogTest\\" + fileName);
try {
file.transferTo(saveFile);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
还是使用 Postman 进行测试
现在就不会覆盖上一张图片了
6. 获取 Cookie
获取单一的 cooking
@RequestMapping("/cookie")
public Object cookie(@CookieValue(value = "java",required = false)String java){
return java;
}
输入 URL 进行访问
发现一片空白,不要慌
F12 打开开发者工具: 点击应用, 点击 Cookie, 点击他下面的
然后开始伪造 Cookie,必须名称是 java, 因为 idea 写的就是 java. 后面的值看你自己
刷新就得到了结果
7. 获取 Header
@RequestMapping("/header")
public Object getHeader(@RequestHeader("Host") String ht) {
return "Host ->" + ht;
}
标头里面的东西全都可以获取
8. 获取 Session
//存储 Session, 只有存了才能读取
//先调用 set 在调用 get
private static final String SESSION_KEY = "USERINFO_SESSION_KEY";
@RequestMapping("/setsession")
public void setSess(HttpServletRequest request) {
HttpSession session = request.getSession();
session.setAttribute(SESSION_KEY, "zhangsan");
}
@RequestMapping("/getsession")
public Object getSession(@SessionAttribute(SESSION_KEY) String name) {
return "session->" + name;
}
3.3 返回数据
1. 返回静态页面
先弄一个前端返回
在 resource 下面的 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>index.html</title>
</head>
<body>
<h1>hello index</h1>
</body>
</html>
在 com.example.demo.Controller 新建一个 TestController
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/index")
public Object getIndex(){
return "/index.html";
}
}
2. 跳转地址: 请求转发(forward)和请求重定向(redirect)
请求转发展示
@RequestMapping("/forward")
public String forward() {
return "forward:/index.html";
}
请求重定向展示
@RequestMapping("/redirect")
public String redirect() {
return "redirect:/index.html";
}
请求重定向:百度
@RequestMapping("/redirect2")
public void redirect2(HttpServletResponse response) throws IOException {
response.sendRedirect("https://www.baidu.com");
}
使用 Fiddler 抓包演示
先输入网址,但是不要按下回车,打开 Fiddler 在按下回车
通过抓包软件可以看到, 原本的localhost:8080/test/redirect2 状态码是302. 请求重定向成功
forward 和 redirect 具体区别如下:
1. 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
2. 请求重定向地址发⽣变化,请求转发地址不发生变化。
3. 请求重定向与直接访问新地址效果⼀直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。
本文完,感谢观看,不足之处请在评论区指出 !