SpringMVC
1.什么是 Spring MVC?
Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称"Spring Web MVC"来⾃其源模块的名称(Spring-webmvc),但它通常被称为"SpringMVC"。
从上述定义我们可以得出两个关键信息
- Spring MVC 是⼀个 Web 框架
- Spring MVC 是基于 Servlet API 构建的
然而要真正的理解什么是 Spring MVC?我们⾸先要搞清楚什么是 MVC?
1.1MVC 定义
MVC 是 Model View Controller 的缩写,它是软件工程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分
1.2 MVC 和 Spring MVC 的关系
MVC 是⼀种思想,而Spring MVC 是对 MVC 思想的具体实现。
总结来说,Spring MVC 是⼀个实现了 MVC 模式,并继承了 Servlet API 的 Web 框架。既然是 Web框架,那么当用户在浏览器中输入了 url 之后,我们的 Spring MVC 项目就可以感知到用户的请求
MVC喝springMVC相当于IoC和DI一样,IOC是思想,DI是实现
2.为什么要学 Spring MVC?
大部分的公司,他们的前后端的数据通信依靠的是http,而http又要求服务器端是一个web框架(web框架就是一个实现了http协议的服务器端)才行,因此我们需要有一个spring的web框架的,这个框架就是springmvc
有人会说springboot也可以做到服务器客户端数据交互,那我就不学springmvc了,当然是不行的!
因为springboot里面也内置了web框架了
这里的spring-boot-starter-web就是springmvc,只不过在springboot里面,名字变了
3.怎么学 Spring MVC?
学习 Spring MVC 我们只需要掌握以下 3 个功能:
- 连接的功能:将用户(浏览器)和 Java 程序连接起来,也就是访问⼀个地址能够调用到我们的
Spring 程序。 - 获取参数的功能:用户访问的时候会带⼀些参数,在程序中要想办法获取到参数。
- 输出数据的功能:执行了业务逻辑之后,要把程序执行的结果返回给用户。
对于 Spring MVC 来说,掌握了以上 3 个功能就相当于掌握了 Spring MVC
3.1Spring MVC 创建和连接
Spring MVC 项目创建和 Spring Boot 创建项目相同(Spring MVC 使用 Spring Boot 的方式创建),在创建的时候选择 Spring Web 就相当于创建了 Spring MVC 的项目。
在 Spring MVC 中使用 @RequestMapping 来实现 URL 路由映射,也就是浏览器连接程序的作用
3.1.1@RequestMapping 注解介绍
@RequestMapping 是 Spring Web 应用程序中最常被用到的注解之⼀,它是用来注册接口的路由映射的。
路由映射:所谓的路由映射指的是,当用户访问⼀个 url 时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射
@RequestMapping 即可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类 + 方法。
java
@Controller
@RequestMapping("/p")
public class PersonController {
@RequestMapping("/index")
public Object index(Person person){
// 获取参数
System.out.println(person.getName() +":"+
person.getPassword());
// 执⾏业务...
return "/index.html";
}
}
@RequestMapping 也可以直接修饰方法
RequestMapping 还可以设置请求时get还是post(啥也不设置就是都可以)
3.1.2@GetMapping 和 PostMapping
@GetMapping能实现http连接,但是只支持get请求
@PostMapping能实现http连接,但是只支持post请求
3.2获取参数
3.2.1 传递单个参数
java
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/test2")
public class TestController2 {
//servlet写法
@RequestMapping("/getname")
public String getName(HttpServletRequest request) {
return "Name:" + request.getParameter("name");
}
@RequestMapping("/getname2")
public String getName2(String name) {
return "Name:" + name;
}
@RequestMapping("/getname3")
public String getName3(String name, Integer age) {
return "Name:" + name + " age:" + age;
}
}
传递多个参数
3.2.2获取对象
java
@RestController
@RequestMapping("/user")
public class UserController {
private static String _SESSION_KEY = "SESSION_KEY";
@RequestMapping("/add")
public User add(User user) {
return user;
}
}
java
@Data
public class User {
private int id;
private String name;
private String password;
private int age;
}
3.2.3后端参数重命名
java
@RequestMapping("/name")
public String name(@RequestParam(value = "n", required = false)
String name) {
return name;
}
拿前端的n匹配后端的name
前端设置的是n=李四,就必须传过来n,也就是在后端value="n"这里
如果传过来的是别的,就会在前端页面报错,但是如果把required = false加上,前端如果传过来的不是n,就不会报错了,但是会是空白页面
3.2.4获取前端JSON对象
获取对象和获取JSON对象是不一样的
java
@RequestMapping("/add_json")
public User addByJson(@RequestBody User user) {
//@RequestBody的意思是从前端的请求body里拿到JSON对象的数据,然后框架将数据进行转换一一赋值给user对象,然后再返回user对象到前端页面上
return user;
}
前端
3.2.5 获取URL中参数@PathVariable
java
@RequestMapping("/detail/{aid}")
public Integer detail(@PathVariable("aid") Integer aid) {
return aid;
}
获取多个url的参数
java
@RequestMapping("/detail2/{aid}/{name}")
public String detail2(@PathVariable("aid") Integer aid, @PathVariable("name") String name) {
return "aid:" + aid + " name:" + name;
}
3.2.6上传文件@RequestPart
java
@RequestMapping("/upload")
public String upload(@RequestPart("myfile") MultipartFile file) throws IOException {
// 1.生成一个唯一的id | UUID = 全球唯一ID -> MAC + 随机种子 + 加密算法
String name = UUID.randomUUID().toString().replace("-", "");
// 2.得到源文件的后缀名
//比如cat.png name得到的就是png
name += (file.getOriginalFilename().
substring(file.getOriginalFilename().lastIndexOf(".")));
String path = "D:\\image\\" + name;
// 保存文件
file.transferTo(new File(path));
return path;
}
@RequestPart("myfile")是给从前端传过来的文件起个名字
MultipartFile file是用文件格式来接收前端传过来的文件
生成唯一ID+得到文件后缀名的操作是为了防止文件覆盖,比如全球十万个人全传的是一个名字的文件,这时候前99999份都被覆盖了
前端上传文件要用post方式
模拟文件发送如下图
点击File之后出来的File的name要等于@RequestPart("myfile")这里的myfile
3.2.7 获取Cookie/Session/header
获取cookie
java
@RequestMapping("/getcookie")
public String getCookie(@CookieValue(value = "java", required = false)
String ck) {
return ck;
}
获取session
java
@RequestMapping("/get_sess")
public String getSess(@SessionAttribute(required = false, value = "SESSION_KEY") String name) {
return name;
}
获取Header
java
@RequestMapping("/header")
@ResponseBody
public String header(@RequestHeader("User-Agent") String userAgent) {
return "userAgent:"+userAgent;
}
3.3返回数据
通过上⾯的学习我们知道,默认请求下无论是 Spring MVC 或者是 Spring Boot 返回的是视图(xxx.html),而现在都是前后端分离的,后端只需要返给给前端数据即可,这个时候我们就需要使用@ResponseBody 注解了。
不加@ResponseBody 的话,浏览器以为你反悔了一个hello.html页面,可是没有这个文件,浏览器就会404,这时候你如果新建一个hello.html页面,就不会报错(如下图图一)
如果想把hello.html当成一个数据,就加上@ResponseBody
@ResponseBody返回的东西会由框架自动判断,如果是字符会转换成 text/html,如果返回的是对象会转换成application/json 返回给前端。
@ResponseBody 可以用来修饰方法或者是修饰类,修饰类表示类中的所有方法都会返回 html 或者json,而不是视图。
@RestController = @Controller + @ResponseBody
4.请求转发或请求重定向
forward VS redirect
return 不但可以返回⼀个视图,还可以实现跳转,跳转的方式有两种:
forward 是请求转发;
redirect:请求重定向。
请求转发是你的请求传到了服务器,服务器再把这个请求转发到另一个地方B,然后服务器会拿到这个B地方的数据,返回给客户端
请求重定向就是客户端向服务器发送请求,服务器告诉客户端我这里没有,你直接去B地获取
forward(请求转发)和 redirect(请求重定向)的区别,举例来说,例如,你告诉你妈妈,裤子在哪,如果你妈妈,说我帮你去找,这就是 forward 请求转发;如果你妈妈告诉你裤子在沙发,那么就是请求 redirect 重定向。
forward 和 redirect 具体区别如下
- 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
- 请求重定向地址发生变化,请求转发地址不发生变化。
- 请求重定向与直接访问新地址效果⼀样,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。