文章目录
- 🎇前言
- 1.MVC
- 1.1 MVC 的定义
- 1.2 MVC 与 Spring MVC的关系
- 2.为嘛要学Spring MVC?
- 3.如何学习 Spring MVC?
- 3.1 Spring MVC 创建和连接
- 3.1.1 @RequestMapping 注解介绍
- 3.1.2 使用@RequestMapping的参数修改请求方法
- 3.1.3 @GetMapping 和 PostMapping
- 3.2 获取参数
- 3.2.1 传递单个参数
- 3.2.2 传递对象
- 3.2.3 表单参数传递/传递多个参数(非对象)
- 3.2.4 后端参数重命名(后端参数映射)
- 3.2.5 @RequestBody 接收JSON对象
- 3.2.6 获取URL中参数@PathVariable
- 3.2.7 上传文件@RequestPart
- 3.2.8 获取Cookie/Session/header
- 3.3 返回数据
- 3.3.1 返回静态页面
- 3.3.2 返回 text/html
- 3.3.3 返回 JSON 对象
- 3.3.4 请求转发或请求重定向
- 🎆总结:
🎇前言
学习SpirngMVC
首先我们要先知道SpringMVC
是什么。SpirngMVC
的全名是Spring Web MVC
,基于Servlet API
构建的原始 Web 框架,从⼀开始就包含在Spring
框架中。它的正式名称Spring Web MVC
来自其源模块的名称(Spring-webmvc),在平常我们称它为Spring MVC
。
上述最重要的两个关键信息:
- Spring MVC 是一个 Web 框架
- Spring MVC 是基于 Servlet API 创建的
Spring MVC 它由两个单词组成(Spring和MVC),Spirng在之前我们看过是什么了(传送门:Spring 核心与设计思想),剩下一个MVC,让我们来看看是什么吧!
1.MVC
1.1 MVC 的定义
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分
为模型、视图和控制器三个基本部分。
- Model(模型): 应用程序中用于处理应用程序数据逻辑的部分;通常模型对象负责在数据库中存取数据
- View(视图): 应用程序中处理数据显示的部分;通常视图是依据模型数据创建的。
- Controller(控制器): 应用程序中处理用户交互的部分;通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
1.2 MVC 与 Spring MVC的关系
MVC 是一种思想,而 Spring MVC 是对 MVC 思想的具体实现。
总的来说,Spring MVC
是一个实现了MVC
模式,并继承了Servlet API
的Web
框架。
2.为嘛要学Spring MVC?
现在绝大部分的 Java 项目都是基于 Spring 或 SpringBoot的,而 Spring 的核心就是 Spring MVC。也就是说 Spring MVC 是 Spring 框架的核心模块,而 SpringBoot 是 Spring 的脚手架,因此我们得出如下结论:现在市面上绝大部分的 Java项目约等于 Spring MVC 项目,这就是我们为啥要学 Spring MVC的原因。
3.如何学习 Spring MVC?
只需熟悉掌握以下三个功能即可:
- 链接功能: 将用户和 Java 程序连接起来,也就是访问一个地址能够调用到 Spring 程序。
- 获取参数的功能: 用户访问的时候会带一些参数,在程序中获取到参数。
- 输出数据的功能: 根据参数执行业务逻辑,把程序执行的结果返回给用户。
对于Spirng MVC来说,掌握了以上3个功能就相当于掌握了Spring MVC来了。
3.1 Spring MVC 创建和连接
Spring MVC 项⽬创建和 Spring Boot 创建项⽬相同(Spring MVC 使⽤ Spring Boot 的方式创建),
在创建的时候选择 Spring Web 就相当于创建了 Spring MVC 的项目。项目的创建可以参考这篇文章(传送门:Spring MVC项目创建)。
Spring 项目离不开注解,我们连接也需要注解,它就是@RequestMapping
3.1.1 @RequestMapping 注解介绍
@RequestMapping 是 Spring Web 应用程序中最常用到的注解之⼀,它是⽤来注册接⼝的路
由映射的。
路由映射: 路由映射指的是当⽤户访问⼀个 url 时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射.
@RequestMapping基本使用方式:
我们实现一个在网页上打印你好 @RequestMapping
。
package com.example.demo.Contronller;
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("/hi")// 路由映射
public String sayHi() {
String res ="你好 @RequestMapping";
return res;
}
}
这里说一下为什么使用两个@RequestMapping
,用在类上面的我们称为一级路由映射,它是为了能找到这个类(一个文件夹里可能有很多类),加在方法称为二级路由映射,为了能找到这个方法(一个类中可能有很多方法)。其实这就像我们点外卖,我们输入地址的时候先输出小区(一级路由映射),在输入几号楼(二级路由映射)。
@RequestMapping 即可修饰类,也可以修饰⽅法,当修饰类和⽅法时,访问的地址是类 + 方法。
当仅修饰方法时:
package com.example.demo.Contronller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller// 让 spring 框架启动时,加载
@ResponseBody// 返回⾮⻚⾯数据
public class UserController {
@RequestMapping("/hi")// 路由映射
public String sayHi() {
String res ="你好 @RequestMapping";
return res;
}
}
3.1.2 使用@RequestMapping的参数修改请求方法
Servlet API
中有 GET、POST、DELETE等等一共八种方法。在这里@RequestMapping
如何修改方法呢?在@RequestMapping
里面有一个参数叫做method
,它默认值是空,我们可以调整它的值来确认使用什么方法,如下图:
package com.example.demo.Contronller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@ResponseBody
public class UserController {
@RequestMapping(value = "/hi",method = RequestMethod.POST)
public String sayHi() {
String res ="你好 @RequestMapping";
return res;
}
}
3.1.3 @GetMapping 和 PostMapping
这两个注解就是@RequestMapping
的子类,它们相当于已经指定了方法类型,只需在使用的时候填入路由地址就行了。
//POST方法
@PostMapping("/hi")
//GET方法
@GetMapping("/hi")
3.2 获取参数
3.2.1 传递单个参数
在 Spring MVC 中可以直接⽤方法中的参数来实现传参,比如以下代码:
@RequestMapping("/getName")
public String getName(String name) {
String res ="你好:"+ name;
return res;
}
我们输入URL:http://127.0.0.1:8080/getName?name=张三
,就会看到响应 :
这里有坑的,我们在设置参数类型时,一定要使用包装类,如果没有用包装类我们没有给后端传参的时,他就会报错,如果我们使用的是包装类,那么就算前端没有传参它也不会报错,只是会显示null。
3.2.2 传递对象
我们准备一个类接收前端发过来的数据,Spring MVC 可以自动实现参数对象的赋值,比如 User 对象:
先创建一个User对象
import lombok.Data;
@Data
class User{
int id;
String name;
}
在写一个方法接收User对象:
@RequestMapping("/getUser")
public String getUser(User user) {
return user.toString();
}
输入URL:http://127.0.0.1:8080/getUser?id=1&name=张三
就可以看到它通过对象里面的toStrin()方法输出的user对象了。
3.2.3 表单参数传递/传递多个参数(非对象)
@RequestMapping("/getUser")
public String getUser(String name,Integer id) {
String res= name +id;
return res;
}
我们输入URL:http://127.0.0.1:8080/getUser?id=1&name=张三
,就可以得到:
注意: 当有多个参数时,前后端进⾏参数匹配时,是以参数的名称进⾏匹配的,因此参数的位置是不影响后端获取参数的结果。
3.2.4 后端参数重命名(后端参数映射)
在有些情况下,前端传递的参数key和我们后端接收的key可能不一致,比如前端传递了一个time给后端,而后端又是由 createtime字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况的画,我们可以使用@RequestParam
来重命名前后端的参数值。
具体代码如下:
@RequestMapping("/getTime")
public String getTime(@RequestParam("time")String createTime) {
return createTime;
}
我们输入URL:http://127.0.0.1:8080/getTime?time=2023-7-4
,就可以得到以下的内容:
这里有一个坑,当我们将参数加上@RequestParam
这个注解时,当前端传递参数时,这个被注解的参数不能为空,不然就会报错,这是为啥呢?我们看看这个注解的源码:
可以看出来,它默认的参数是 true,因此必须传输数据,不然就会报400的错误码;如果当传递时想要让他为空并且不报错,这个也很好操作,我们只需将它的值调成false就可以了(@RequestParam(value = "time",required = false)
)
3.2.5 @RequestBody 接收JSON对象
我们前面也有一个传递对象,但是他个这个JSON对象不一样,这个JSON对象是这么样接收的呢,看下方的代码。
@RequestMapping(value = "/getJSON",method = RequestMethod.POST)
public String getJSON(@RequestBody User user) {
return user.toString();
}
我们拿JSON对象是在传值的body里面拿的数据,和上方的对象不太一样。
3.2.6 获取URL中参数@PathVariable
代码如下:
@RequestMapping("/getParam/{username}/{password}")
public String getParam(@PathVariable String username,
@PathVariable String password) {
return username +":" +password;
}
这里面路由映射中,有两个参数加了花括号,这个表示它两个是动态参数;我们输入URL:http://127.0.0.1:8080/getParam/张三/123123
验证是否可以在URL中拿到数据,结果如下:
3.2.7 上传文件@RequestPart
我们举一个简单的例子,我们先传一张照片,代码如下:
@RequestMapping("upfile")
public String upFile(@RequestParam("myfile") MultipartFile file) throws IOException {
//上传的路径
String path = "F:\\info\\img.png";
file.transferTo(new File(path));
return path+"上传成功";
}
上方代码是传一个照片,传到path参数路径下。我们验证需要配合Postman来完成,使用Postman发送请求:
我们打开我们设置的路径,看看有没有上传的图片,看下图完全没有问题:
虽然上方方法的使用没有问题,但是,我们再次上传图片时,会把上一次上传的图片给覆盖掉,因为我们把上传的路径写死了,这怎么办呢?往下看:
这个问题就很好解决,我们把文件的名字改成随机的,再将它拼接在path上面;只这样还不行,我们还要把它的后缀名给取出来,代码如下:
@RequestMapping("upfile")
public String upFile(@RequestParam("myfile") MultipartFile file) throws IOException {
//上传的路径
String path = "F:\\info\\";
//路径+【文件名】
path += UUID.randomUUID().toString();
//路径+文件名+【后缀】
path += file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
file.transferTo(new File(path));
return path+"上传成功";
}
我们再用Postman多上传几个图片看看,打开path路径,完全没有问题:
3.2.8 获取Cookie/Session/header
🐣获取 Request 和 Response 对象
在SpringMVC中内置了Request对象和Response对象,我们可以直接使用
@RequestMapping("/param1")
public String param1(HttpServletResponse response, HttpServletRequest request) {
String name =request.getParameter("name");
Cookie[] cookies =request.getCookies();
return name+"你好";
}
🐣传统获取 header/cookie
@RequestMapping("/param10")
public String param2(HttpServletResponse response, HttpServletRequest request) {
String name = request.getParameter("name");
// 获取所有 cookie 信息
Cookie[] cookies = request.getCookies();
String userAgent = request.getHeader("User-Agent");
return name + ":"+userAgent;
}
🐣简洁的获取 Cookie—@CookieValue
@RequestMapping("/cookie")
public String cookie(@CookieValue("dabaicai") String bite) {
return "cookie:" + bite;
}
🐣简洁获取 Header—@RequestHeader
@RequestMapping("/header")
public String header(@RequestHeader("User-Agent") String userAgent) {
return "userAgent:"+userAgent;
}
🐣Session 存储和获取
Session 存储和 Servlet 类似,是使⽤ HttpServletRequest 中获取的,如下代码所示:
@RequestMapping("/setsess")
public String setsess(HttpServletRequest request) {
// 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建⼀个session
HttpSession session = request.getSession(true);
if(session!=null){
session.setAttribute("username","java");
}
return "session 存储成功";
}
🐣获取 Session 可以使⽤ HttpServletRequest,如下代码所示:
@RequestMapping("/sess")
public String sess(HttpServletRequest request) {
// 如果 session 不存在,不会⾃动创建
HttpSession session = request.getSession(false);
String username = "暂⽆";
if(session!=null && session.getAttribute("username")!=null){
username = (String) session.getAttribute("username");
}
return "username:"+username;
}
🐣获取 Session 更简洁的⽅式:
@RequestMapping("/sess2")
public String sess2(@SessionAttribute(value = "username",required = false)String username) {
return "username:"+username;
}
3.3 返回数据
通过上⾯的学习我们知道,默认请求下⽆论是 Spring MVC 或者是 Spring Boot 返回的是视图,而现在都是前后端分离的,后端只需要返给给前端数据即可,这个时候我们就需要使⽤@ResponseBody 注解了.
3.3.1 返回静态页面
在目录resources/static/
下创建前端页面 index.html,之后再将它返回给前端:
package com.example.demo.Contronller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("test")
public class TestController {
@RequestMapping("/index")
public Object index(){
// 执⾏业务...
// 返回view -> index.html
return "/index.html";
}
}
3.3.2 返回 text/html
@RequestMapping("/text")
public String text() {
return "<h1>Hello,HTML~</h1>";
}
3.3.3 返回 JSON 对象
我们使用Map,将它返回给前端,他会自动解析成JSON对象。
@RequestMapping("getjson")
public HashMap<String, String> getJosn() {
HashMap<String, String> map = new HashMap<>();
map.put("Java", "Java Value");
map.put("MySQL", "MySQL Value");
map.put("Redis", "Redis Value");
return map;
}
3.3.4 请求转发或请求重定向
return 不但可以返回⼀个视图,还可以实现跳转,跳转的⽅式有两种:
- forward 是请求转发;
- redirect:请求重定向
举例说明 forward 和 redirect:
forward(请求转发)和 redirect(请求重定向)的区别:我向吃辣条,我给我儿子说,你去帮我买,这就是 forward 请求转发;如果我想吃辣条,我自己去买,这就是 redirect 重定向。
forward 和 redirect 具体区别如下:
- 请求重定向(redirect)将请求重新定位到资源;请求转发(forward)服务器端转发。
- 请求重定向地址发⽣变化,请求转发地址不发⽣变化。
- 请求重定向与直接访问新地址效果⼀直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问
🎆总结:
在SpringMVC中,我们用的最多的就是注解,这些注解可以让我们可能需要几行,甚至十几行的代码简化成一行代码,因此注释在SpringMVC中很重要,我们上方也仅仅是举出了一些常用的例子,如果需要更多的注解,可以去看下面这个连接里面的注解的解释(传送门:官方api)