官方对于Spring MVC的描述为:
Spring Web MVC是基于Servlet API框架构建的原始Web框架,从一开始就包含在Spring框架中。它的正式名称“Spring Web MVC”来自其源模块的名称(Spring-webmvc),但它通常被称为“Spring-MVC”。
目录
Spring MVC 介绍
学习Spring MVC
连接
@RequestMapping
指定类型
获取参数
获取对象
参数重命名(参数映射)
接收Json对象
从URL中获取参数
上传文件
获取Cookie
获取Session
获取Header
编辑
请求定向和请求转发
Spring MVC 介绍
MVC 是Model View Controller的缩写,是软件工程中的一种软件架构模式,它把软件系统分成模型、视图和控制器三个部分。
MVC是一种思想,而Spring MVC是对MVC思想的具体实现:
Spring MVC是一个实现了MVC模式,并继承了Servlet API的Web框架。既然是Web框架,那么当用户在浏览器中输入了url之后,我们的Spring MVC项目就可以感知到用户的请求。
现在绝大多数的Java项目都是基于Spring 或Spring Boot,而Spring的核心就是Spring MVC。
在创建Spring Boot项目时,我们勾选的Spring Web框架其实就是Spring MVC框架:
学习Spring MVC
学习Spring MVC需要掌握三个功能:
连接、获取参数、输入数据。
连接
在项目创建好之后,创建一个UserController类,实现用户到Spring程序的互联互通:
我们用到了三个注释:@Controller @ResponseBody @RequestMapping
@Controller:五大类注解,表示把这个类添加到IoC容器中,供Spring拿到。
@ResponseBody:表示把这个Java对象转换成json格式相关的内容,表示返回非页面数据
通过@RestController = @Controller + @ResponseBody 可以完成两个注释的内容合二为一。
@RequestMapping
@RequestMapping既可以修饰类也可以修饰方法,当修饰类和方法时,访问的地址是类 + 方法。
并且也可以直接修饰方法。
指定类型
@RequestMapping可以为GET方法也可以为POST方法,如果不规定则两个方法都可以用。但如果要求只能是POST或者只能是GET方法呢?
想只要GET方法,有两种写法:
- @RequestMapping(value = "/user",method = RequestMethod.GET)
- @GetMapping("/index")
想只要POST方法,有两种写法:
- @RequestMapping(value = "/user",method = RequestMethod.POST)
- @PostMapping("/user")
获取参数
在Spring MVC中可以直接用方法中的参数来实现传参,相比于Servlet中大费周折的getParameter等方式简单了很多。
在Spring MVC中,只需要方法的形参和前端传入的变量名相同,就能够直接获取到相关的参数。
获取对象
Spring MVC可以自动实现参数对象的赋值:
并且当有多个参数的时候,前后端匹配数据的时候以名称进行匹配的,因此参数的位置不影响后端获取的参数的结果。
参数重命名(参数映射)
和前面提到的一样,如果前后端名称不一样但是想要获取到匹配的数据,此时可以使用@RequestParam 来重命名前后端的参数值。
例如,前端传来的参数为username,但是后端为name,此时给后端参数重命名:
并且如果某个参数是非必传参数的话,可以设置@RequestParam中的requird=false来避免不传递时报错:
接收Json对象
这次我们不用表单的形式来传对象,而是使用Json的格式来传递对象。只有使用了@RequestBody后才能正确的把对象解析出来。
从URL中获取参数
对于前面的通过表单的形式拿数据,主要是通过URL中?后面的值来传递。现在还有一种方式可以传递,就是通过@PathVariable直接拿到URL中的参数。
例如: localhost:8080/user/123/zhangsan/123456
这种方式和问号后面加上数据相对比有两个优点:
1.对于搜索引擎来说,抓取关键字权重更高
2.URL更简洁
@RequestMapping时需要加上相应的属性,在传递形参的时候使用@PathVarable来获取,如果传递的参数和属性名不同时,也可以使用重命名。
如果RequestMapping和形参名称不一样就可以使用@PathVarable的重命名来表示。
- @PathVariable ->基础URL里面的参数(?之前的参数)
- @RequestParm->URL参数部分的参数(?之后的参数)
上传文件
使用@RequestPart来上传文件。
之后使用Postman来模拟前端发来的图片:
在新文件的地址中,可以看到新的文件已经生成。但是有几个问题,比如这样重复一次,新文件会覆盖旧文件。并且不能重命名文件。
最靠谱的保证文件名唯一的命名方法,是使用UUID。简单说这个UUID是不会重复的。
UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符。
首先我们要解决文件格式的问题。之前我们使用的是png,如果原文件是jpg还好说,如果是gif等就会出错。所以我们需要获取原生的文件名,把文件名的前部分使用UUID替换,文件名的后缀截取到再重命名。
这样即使是上传同样的文件,也不会覆盖之前的文件。
@RestController
public class UserController {
@RequestMapping("/upload")
public Object upload(@RequestPart("myimg") MultipartFile file){
String fileName = UUID.randomUUID()+file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
File saveFile = new File("C:\\MyCode\\" + fileName);
try {
file.transferTo(saveFile);
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
获取Cookie
在之前的Servlet中,我们已经使用过HttpServletResponse和HttpServletRequest来获取cookie,我们现在使用更简单的方法获取:
通过@CookieValue注解来把获取到的cookie得到,代码中重命名的是java,所以当我们自己伪造一个名字为java的cookie后就可以获取到。
获取Session
通过@SessionAttribute来方便的获取到Session。
获取Header
使用@RequestHeader获取到Header。
请求定向和请求转发
请求转发和请求重定向有什么区别? | Javaᶜⁿ 面试突击 (javacn.site)