目录
[前言:认识Spring MVC](#前言:认识Spring MVC)
🌷1、@RequestMapping注解:注册接⼝的路由映射(默认返回页面)
[🌷 3、组合注解@RestController = @ResponseBody + @Controller](#🌷 3、组合注解@RestController = @ResponseBody + @Controller)
[🌷4、支持Get请求的2种写法@GetMapping + @RequestMapping](#🌷4、支持Get请求的2种写法@GetMapping + @RequestMapping)
[🌷 5、只支持Post请求的两种方法](#🌷 5、只支持Post请求的两种方法)
🌷4、后端对从前端接收到的参数重命名@RequestParam
[🌷 7、接收文件@RequestPart](#🌷 7、接收文件@RequestPart)
[🌷 8、获取Cookie](#🌷 8、获取Cookie)
[🌷 9、获取和设置Session](#🌷 9、获取和设置Session)
[🌷 10、获取Header](#🌷 10、获取Header)
前言:认识Spring MVC
官方定义:Spring Web MVC是基于Servlet API构建的原始Spring框架,从一开始就包含在Spring框架中,一般我们说Spring MVC,Spring Web,Spring Web MVC都是同一个意思。
🌷1、什么是MVC?
MVC 是 Model View Controller 的缩写,它是软件⼯程中的⼀种软件架构模式,它把软件系统分
为模型、视图和控制器三个基本部分。(早期MVC思想,现在已经不太用了。)

当前的MVC:更适合称为Spring Web,因为现在很多项目都使用了前后端分离的思想。MVC是一种思想,Spring MVC是对MVC思想的具体体现。
(1)MVC是一个Spring框架;
(2)MVC是一个Web项目。继承了 Servlet API 的 Web 框架(当⽤户在浏览器中输⼊了 url 之后,我们的 Spring MVC 项⽬就可以感知到⽤户的请求)。
我们之前在创建SpringBoot项目的时候,引入了Spring Web,因此已经包含了Spring MVC。所以我们的之前的项目也可以称为SpringMVC项目或者Spring Web项目。

Spring、SpringBoot、SpringWeb的关系?
SpringMVC也就是这个高铁可以被外界使用。一个项目可以是SpringBoot项目,也可以是SpringWeb项目,但是SpringWeb不一定是SpringBoot项目,SpringBoot项目也不一定是SpringWeb项目。在没有SpringWeb之前,也是由SpringWeb项目的,是基于SpringCore项目创建的。
所以因为SpringMVC是一个Web项目,用户通过url就可以访问,所以我们主要学习下面三部分:
1、建立连接:不一定是浏览器
2、请求:接收参数
3、响应:返回结果
一、建立连接(5个注解)
主要学习5个注解。
🌷1、@RequestMapping注解:注册接⼝的路由映射(默认返回页面)
这个相当于Servlet阶段的@WebServlet。
路由映射:当用户访问一个url的时候,将用户的请求对应到程序的某个类的某个方法的过程。
返回一个静态页面:

(1)@RequestMapping既是类注解,也是方法注解。访问的url等于类注解+方法注解。
(2)虽然不写类注解也可以访问,但是实际中我们默认是两个RequestMapping都写得。因为只写方法注解可能会地址相同,但是每个类都是不同的,所以在一定程度上可以避免地址相同的现象。
(3)类注解@RequestMapping要搭配五大注解使用,一般使用@Controller,其他的五大注解使用不稳定,有时候成功,有时候不成功,我们就使用@Controller。

🌷2、@ResponseBody注解:表示返回的是数据


@ResponseBody注解是一个类注解,写在类上就表示该类下所有的方法都是数据,而不是页面。因此一个类里的方法既要返回页面,又要返回数据,就不适合用这个方法了。
🌷 3、组合注解@RestController = @ResponseBody + @Controller


🌷4、支持Get请求的2种写法@GetMapping + @RequestMapping
Postman测试,发现**@RequestMapping已经支持Get,Post等其他请求。**
其他2种只支持get的写法:

🌷 5、只支持Post请求的两种方法

简单总结:
1、@ResquestMapping实现url的映射,搭配@Controller使用;默认返回的是页面;支持Post和get灯请求;
2、@ResponseBody返回数据
3、@RestController=@ResponseBody+@Controller;
4、只支持post方法:@PostMapping或者@RequestMapping(value = "/A",method= RequestMethod.POST)
5、只支持get方法:@GetMapping或者@RequestMapping(value = "/B",method = RequestMethod.GET)
二、请求:从前端接收参数(重点!!!)
🌷1、接收单个参数
方式1:Servle方式


方式2:方法中直接拿


注意:url的name和方法中的String name名字要对应上。
🌷2、接收多个参数
方式1:Servlet方式


方式2:方法中直接拿


注意:
情况1::我们在方法中先输入age,再输入name;url先输入name,再输入age。发现不影响结果。
结论1:
(1)参数的顺序和url传参的顺序无关;
(2)并且帮我们进行了数据类型的转化。
情况2:方法中有两个参数,但是url中只传递name,age显示为null;
结论:
(1)age为Integer类型,不传参会显示null;
(2)传一个String类型参数,会显示400异常; 400表示客户端发生错误。
对于 Spring MVC 框架而言,它将请求参数转换成值对象类中各属性对应的数据类型。
情况3:方法中有两个参数(将age类型由Integer改为Int),url只传递name,不传递age,此时显示500异常。500表示服务器端错误。
传递参数类型错误,会显示400异常。
🌷3、接收非常多的参数
可以一个一个写,但是存在问题:(1)非常麻烦(2)代码的耦合度太高。
方式1:将参数封装成一个对象
Student类:如果要加别的参数,直接在类中加属性就好,不会影响到其他的代码。



方式2:表单传递(这是前端传参方式,与接收参数的方式无关)
通过ajax,form表单,浏览器传参等方式都可以。
form表单形式:

也可以这种写法:
🌷4、后端对从前端接收到的参数重命名@RequestParam
比如前端在传递name的时候,简写为了n,但是我后端写的时候,不想用n这个字母,就想换成name,这个时候就要用后端参数的重命名方法了,在接收参数的时候直接修改名称。


注意:如果不传递n值,显示400错误。
说n是一个必传参数,这个时候我们要对n进行一个设置:required = false。
🌷5、接收Json格式@RequestBody
**情况1:**加RequestBody,postman使用Json格式传递数据,显示正确。
@RequestBody表示从前端接收一个json字符串,Spring帮我们将这个Json字符串转为对象。

postman测试:模拟从前端发送Json格式的数据

Fidder抓包显示结果也正确

**情况2:**加了@RequestBody,postman使用form表单形式提交数据,发现显示415错误。
@RequestBody不支持对象。

🌷6、接收URL中的参数@PathVariable并重命名

注意:
(1)字段的名称之间要对应。
(2)情况3中重命名这种方式,参数默认是必传的,如果不想要传参数,要设置required=false。
postman测试情况1:


postman测试情况2:
postman测试情况3:

🌷 7、接收文件@RequestPart

Postman测试:
抓包工具Fidder

🌷 8、获取Cookie

**情况1:@CookieVaule默认是要传参的(如果不要传参,设置required=false)否则不设置false,但是url中还不传参就会报错,所以我们自己设置一下cookie信息。**F12打开如下界面,自己手动设置cookie信息。(说明cookie是可以人工设置的,造假的。)

此时url再次访问:成功。
情况2:设置required=false

此时url再访问,不报错了。

(3)cookie重命名


🌷 9、获取和设置Session
(1)获取session:@SessionAttrible也是默认要传参


(2)设置session: session.setAttribute


设置完成之后,cookie中就多了一个sessionId。

此时再获取session,就可以访问到了。

🌷 10、获取Header
比如Fidder中的这些都是Header信息。

但是可以观察到,上面的格式都是以-来分隔的,一般我们要将它重命名。比如我们现在要获取User-Agent这个信息,先重命名为userAgent后再获取。

Fidder中的这个信息与我们url中获取到的结果一致。说明成功获取了。


同样的,@RequestHeader默认要传参,设置非必传参数:required = false。


简单总结:
1、获取单个多个参数:直接从方法名中拿;
2、获取非常多参数:将参数封装侧好难过一个对象,也是直接方法中拿;
3、后端参数重命名:@RequestParam(name="前端拿到的A名称" String B是新名称);
4、很多注解都是默认要传参的,设置非必传参数用required = false;
5、方法参数中写@RequestBody 接收JSON对象;
6、@PathVariable Integer shopId接收Url中的参数;@RequestMapping中的url映射更新为"/映射/{shopId}"
7、@RequestPart("file1") MultipartFile file上传文件,上传的文件都保存到服务器上file.transferTo(new file("路径名"));
8、@CookieValue获取cookie;
9、@sessiongetAttribute获取session,session.getAttribute设置session;
10、@RequestHeader("A-B") String AB获取Header并重命名。
三、响应:返回数据
已经知道的:@RequestMapping默认返回静态页面, @ResponseBody返回数据。
🌷1、返回Json对象

Fidder抓包:

🌷2、区分请求转发与请求重定向(重要)
牵扯到页面的转换。
(1)forward请求转发:服务器进行转发,服务器内部处理,对内;
redirect请求重定向:请求资源重定向,对外。
(3)请求重定向url会发生变化。
(3)请求重定向与直接访问新地址效果一样,不存在原来的外部资源不能访问;但是请求转发,服务器端转发可能会造成原外部资源不能访问。
举例:我在网上商城A品牌买了手机,现在出了点问题,我去找客服,如果客服说我们只负责销售,维修的话要自行去线下品牌店维修,这就是请求重定向;如果客服说,好的,他们来负责,然后客服联系了他们自己的维修厂家帮我修好或者采取其他方式帮我修好,我不关心方式,是他们自己内部处理好,属于请求转发。
(1)注意观察url的区别


(2)请求转发的问题
请求转发forward如果资源和转发的⻚⾯不在⼀个⽬录下,会导致外部资源不可访问。重定向 redirect则可以正常访问。
比如 index.html中引入了hello.js,forward会报错,redirect是正常的。

