一、什么是 SpringMVC
前面我们了解了Spring、SpringBoot,那么 Spring MVC 又是什么呢?关于三者,我们可以这样理解:Spring MVC 是 Spring 框架的核心模块,而 Spring Boot 是 Spring 的脚手架。
Spring MVC 又称作 Spring Web MVC,是基于 Servlet API 构建的原始 Web 框架。Spring MVC 从一开始就包含在 Spring 框架中,是 Spring 框架的核心模块。
其中MVC 是一种思想,而 Spring MVC 是对 MVC 思想的具体实现。
二、MVC 架构模式
此前,我们已经对 Spring 有了足够的了解了,那么MVC是什么?
MVC 全称为 Model View Controller,它是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。
- Model(模型):模型层代表应用程序的数据和业务逻辑。它负责从数据库或其他数据源中获取数据,并对数据进行处理和管理。
- View(视图):视图层是用户界面的呈现层,负责展示和渲染数据给用户。
- Controller(控制器):控制器层负责接收和处理用户的请求,并根据请求调度合适的模型和视图进行处理。
其中 MVC 模式下业务执行流程如下图所示:
- 首先用户的请求先到达 Controller
- 然后 Controller 根据请求调度 Model 层
- Model 层处理请求信息,并将数据结果返回给 Controller 层
- Controller 根据返回的结果调度 View 层
- View 处理结果数据,并将最终生成的页面呈现给用户
三、SpringMVC 核心功能
1、路由映射
路由映射:所谓的路由映射指的是,当用户访问⼀个 url 时,将用户的请求对应到程序中某个类的某个方法的过程就叫路由映射。
注:在 SringMVC 中可以使用 @RequestMapping 来注册接口的路由映射。 @RequestMapping 即可修饰类,也可以修饰方法,当同时修饰类和方法时,访问的 url 需要同时携带类和方法的路由。
使用示例:
// @RestController 是一个组合注解,作用是设置响应主体,后续介绍 @RestController @RequestMapping("/test") public class TestController { @RequestMapping("/hello") public String sayHello() { return "hello SpringMVC!"; } @PostMapping("/hello2") public String sayHello2() { return "hello SpringMVC2!"; } }
访问 “hello SpringMVC!” 的 url :127.0.0.1:8080/test/hello
访问 “hello SpringMVC2!” 的 url :127.0.0.1:8080/test/hello2
补充说明:
- 使用
@RequestMapping
注册的路由既可以处理所有的HTTP
请求。- 可以设置 @RequestMapping 注解中的
method
的值,实现处理单一请求。如:@RequestMapping(value = “/hello2”,method = RequestMethod.GET)- 可以设置 @RequestMapping 注解中的
method
的值,实现处理单一请求。如:@RequestMapping(value = “/hello2”,method = RequestMethod.GET)
2、获取参数
(1)获取单个参数
@RequestMapping("/getname") public void getName(String name) { System.out.println("name:"+name); }
当访问 127.0.0.1:8080/test/getname?name=lihua,或者使用 form 表单中存在一个 名称为 name 的参数时,可在方法中得到参数的值。不存在同名参数即为空。
(2)获取多个参数
@RequestMapping("/getname") public void getName(String name,String pwd) { System.out.println("name:"+name+";pwd:"+pwd); }
当访问 127.0.0.1:8080/test/getname?name=lihua&pwd=123,或者使用 form 表单提交同名参数时,可在方法中得到参数的值。不存在同名参数即为空。
当我们传递多个参数的时候,我们也可以使用 对象
接收:
@RequestMapping("/getuser") public void getName(User user) { System.out.println(user.toString()); }
注意:当有多个参数时,在进行参数匹配时,是以参数的 名称 进行匹配的,因此参数的位置是不影响后端获取参数的结果的。未匹配到的参数默认为 null。
(3)后端参数重命名
在某些场景下,我们后端接收的参数使用的 key 可能不同于前端传递的参数的 key 值。这个时候我们可以使用 @RequestParam 来重命名参数名。
@RequestMapping("/getname") public void getUser(@RequestParam("n") String name, String pwd) { System.out.println("name:"+name+";pwd:"+pwd); }
注:此时前端传递参数时,必须存在参数名为 n 的参数,否则会报错。这是因为@RequestParam 注解中有一个参数 required 默认为 required = true,也就是该参数必须传递。如果将其设置为 false ,获取不到则默认为 null。
(4)接收 JSON 对象
@RequestMapping("/getjson") public void getJson(@RequestBody User user) { System.out.println(user.toString()); }
- 前端通过 JSON 提交的数据,后端必须使用
@RequestBody
进行接收。 - 使用 @RequestBody 注解可以让 Spring MVC 自动将请求主体的内容转换为方法参数所需的对象或类型。
(5)获取URL中参数
@RequestMapping("/geturlpart/{name}/{pwd}") public void getUrlpart(@PathVariable("name") String name ,@PathVariable("pwd") String password) { System.out.println("name: "+name+" ;password: "+password); }
- 其中
{name}
和{pwd}
是路径参数,用于从请求 URL 中获取对应的值。 @PathVariable
注解表示将路径参数绑定到方法的参数上。- @PathVariable 中有一个 required 参数,默认为true,即为必传。可设置为false,置为可选参数。@PathVariable(value = “pwd”, required = false)
(6)获取上传的文件
@RequestMapping("/upload") public String upload(@RequestPart("myfile")MultipartFile file) throws IOException { // 1.生成一个唯一 id String id = UUID.randomUUID().toString().replace("-",""); // 2.获取源文件后缀名 String suffix = file.getOriginalFilename(). substring(file.getOriginalFilename().lastIndexOf(".")); // 3.设置文件完整保存路径 String path = "D:/resource/"+id+suffix; file.transferTo(new File(path)); return path; }
@RequestPart("myfile")
注解用于将请求中名为 “myfile” 的二进制数据部分绑定到 MultipartFile 类型的方法参数 file 上。UUID.randomUUID().toString().replace("-", "")
这行代码的作用是生成一个不包含连字符的随机字符串ID。transferTo(File dest)
方法会将当前 File 对象表示的文件的内容拷贝到目标文件 dest 中。如果目标文件已经存在,该方法将会覆盖目标文件的内容。如果目标文件不存在,该方法将会自动创建目标文件并将内容写入其中。
(7)获取 Header
@CookieValue
注解用于将指定名称的 Header 值绑定到方法参数上。
@RequestMapping("/getheader") public void header(@RequestHeader("User-Agent") String userAgent) { System.out.println("userAgent:"+userAgent); }
(8)获取Cookie
@CookieValue
注解用于将指定名称的 Cookie 值绑定到方法参数上。
@RequestMapping("/getcookie") public void getCookie(@CookieValue(value = "mycookie",required = false) String mycookie) { System.out.println("mycookie: "+mycookie); }
(9)获取Session
@SessionAttribute
注解可用于从会话中获取指定名称的属性值,并将其绑定到控制器方法的参数中。
@RequestMapping("/getsession") public void sess2(@SessionAttribute(value = "username",required = false) String username) { System.out.println("username:"+username); }
3、返回数据
@ResponseBody
标记方法,会将标记方法的返回值直接作为响应主体返回给客户端。 再返回的过程中 Spring MVC 将会自动将方法的返回值转换为适当的格式。
@ResponseBody @RequestMapping("/get1") public String get1(){ return "<h1>标题1</h1>"; }
@ResponseBody @RequestMapping("/get2") public User get2(){ return new User(); }
@ResponseBody
可以用来修饰方法或者是修饰类。如果修饰类,表示类中的所有方法的返回值,都直接作为响应主体返回给客户端。- @ResponseBody 标记的方法,返回的值如果是字符串,根据字符串内容会转换成
text/html
,或普通字符串
。如果返回的是对象会转换成 application/json 返回给前端。@RestController
= @Controller + @ResponseBody。用来修饰类。
四、请求转发和请求重定向
1、请求转发
请求转发(forward):请求转发是指服务器中的接收到客户端的请求后,将请求转发给服务器中的另一个资源进行处理,并将处理结果返回给客户端。在请求转发过程中,客户端浏览器并不知道服务器进行了转发,它认为仍然是与最初的URL进行交互。请求转发使用的是服务器内部的跳转,URL地址栏的URL不会改变。
具体实现方法:
得到转发器 request.getRequestDispatcher(“/要跳转到地址”)
调用转发器的方法: forward(request, response)
完整方法:
request.getRequestDispatcher(“/url”).forward(request, response);
请求转发的特点:
- 请求转发是服务器的行为,不支持跨域访问,只能跳转到当前应用中的资源。
- 整个请求转发的过程仅涉及一次请求和一次响应。请求转发之后,浏览器地址栏中的 URL 不会发生变化,因此浏览器不知道在服务器内部发生了转发行为,更无法得知转发的次数。
- 参与请求转发的 Web 资源之间共享同一
request
对象和response
对象。
2、请求重定向
请求重定向(redirect):请求重定向是指服务器接收到客户端的请求后,发送一个HTTP响应给客户端,告诉它需要重新发送一个新的请求到指定的URL。客户端收到响应后会立即发送一个新的请求到指定的URL。在请求重定向过程中,URL地址栏会显示重定向的URL。
具体实现方法:
response.sendRedirect(“访问的地址”);
请求重定向的特点:
- 请求重定向是客户端的行为,一大特点是支持跨域访问。
- 请求重定向涉及到两次请求和两次响应,第一次请求返回一个302重定向响应,客户端收到302响应后请求重定向的url收到第二次响应。
- 请求重定向两次请求响应分别对应不同的 request/response 对象。
3、小结
区别 | 转发 | 重定向 |
行为类型 | 服务器行为 | 客户端行为 |
浏览器地址栏URL是否发生改变 | 否 | 是 |
是否支持跨域跳转 | 否 | 是 |
请求与响应的次数 | 一次请求和一次响应 | 两次请求和两次响应 |
是否共享 request 对象和 response 对象 |
是 | 否 |
速度 | 相对较快 | 相对较慢 |