目录
[什么是spring web mvc:](#什么是spring web mvc:)
[2. @RequestMapping 是GET还是POST请求](#2. @RequestMapping 是GET还是POST请求)
[三. Postman](#三. Postman)
什么是spring mvc:
Spring MVC 是基于 Servlet API 构建的原始 Web 框架,从⼀开始就包含在 Spring 框架中。它的正式名称"Spring Web MVC"来⾃其源模块的名称(Spring-webmvc),但它通常被称为spring mvc.
spring web mvc就是一个web框架.
什么是MVC:
MVC: model view controller.
它是软件⼯程中的⼀种软件架构设计模式 ,它把软件系统分为模型、视图和控制器 三个基本部分.

MVC是⼀种架构设计模式,也⼀种思想, ⽽ Spring MVC是对 MVC思想的具体实现.除此之外,Spring MVC还是⼀个Web框架.总结来说,Spring MVC是⼀个实现了MVC模式的Web框架.
一.创建一个spring项目

springboot版本选择:选择不带SNAPSHOT的就行,
随着springBoot的更新,不同的时间创建,版本可能会不同,只需要选择不带SNAPSHOT的就行.
(带有SNAPSHOT的是可能会进行后台修改的,若修改后,可能原来的一些功能就不能正常执行了;而别的都是确定发布,不会再更新的)

创建spring mvc项目:

这就创建好了springBoot项目:

这几个文件在项目中使用不到,可以选择删除:

二.实现功能:
在springMVC中,用RequestMaping注解 来实现**URL路径映射.**也就是 进行浏览器连接程序.
创建helloController.java项目:

建立连接:
实现 用户通过浏览器和程序交互:
代码如下:
java
@RestController
public class helloController {
//注解:url路径
@RequestMapping("/say")
public String say(){
return "hello spring mvc";
}
}
方法名,和路径名不必相同.

访问路径: http://127.0.0.1:8080/say

@RequestMapping注解:
@RequestMapping注解是springmvc项目中的常用注解之一,用来注册注册接口的路径映射.
表示服务器收到请求时,路径为 /say 的请求会调用 say这个方法.
**路径映射:**当访问一个URL时,将用户的请求对应到程序的某个类的某个方法上,就叫路径映射。
1.@RequestMapping注解的使用:
RequestMapping注解既可以修饰类,也可以修饰方法,当修饰类和路径时,访问路径是:类路径+方法路径。
修饰类时:设置映射请求的请求路径的初识信息
修饰方法时:设置映射请求的请求路径的具体信息。


注意:
1>.路径名前面的斜杠 / 加不加都可以,sping启动时,会进行判断,没有加时,sping会自动补充上一个斜杠.(规范写法是加的)

浏览器访问http://127.0.0.1:8080/hello/say路径,正常执行.
2>.RequestMapping的URL可以有多层,访问路径为 : 类路径+方法路径.

浏览器访问路径为:http://127.0.0.1:8080/hello/m1/say/f1

2. @RequestMapping 尽行的是GET还是POST请求
通过fiddler抓包观察一下:

可以观察到,发送的是GET请求.
那么RequestMaping能否发送POST请求呢?
创建test.html,通过form表单创建请求:
前端代码放在resource.static目录下,访问方式为: 127.0.0.1:8080/test.html

通过浏览器访问test.html:

点击"发送请求"按钮,跳转到了hello/say路径下:

若在static的多层文件夹下,以static为根目录,向下逐层写路径名即可


因此,@RequestMapping既支持GET请求,又支持POST请求.
3.指定请求方法

既然RequestMaping就能实现功能,那么@RestController又是干嘛呢?
@RestController注解:
当去掉@RestController,再次运行代码:

浏览器访问:

程序报了404,无法找到该页面。
这就是@RestController的作用:
一个项目中会有很多类,每个类中会有很多方法,spring会对所有类进行扫描,当加了@RestController注解的类,spring才会扫描该类中的方法,看是否有RequestMapping注解。
这只是RestController其中的一个功能,别的之后再谈。
三. Postman
Postman是一个工具,是一个接口测试工具.
随着项目的深入,不难发现一个问题,后端程序员在测试代码时,还要实现前端代码,这就带来了很大的压力,既要学习后端技能,还有会写前端代码.
随着互联⽹的发展,也随着项⽬难度的增加,企业也按照开发的功能,把⼈员拆分成了不同的团队.界⾯ 显⽰交给"前端开发⼯程师",业务逻辑的实现交给 "后端开发⼯程师". 后端开发⼯程师,不要求也不需要掌握前端技能了.
因此,为了能够提高程序员对自己写的代码的测试效率,Postman工具就实现了这一功能.
下载安装
下载链接: https://www.postman.com/downloads/
下载后,会有升级提示,无需升级,点击dismiss即可

1.创建请求
创建文件夹:


创建请求:


这就创建好了一个请求.
界面分析:

2.参数类型
1>.传普通参数
学习HTTP时,通过URL访问某一资源时,URL中的查询字符串就是传入的 请求参数.
URL格式:

当书写请求路径时,若路径中带有请求字符串,
Postman会检测到,并自动填入参数列表中:

也可以直接通过填写表格进行传参.
2>.form-data
表单提交的数据, 在 form 标签中加上 enctyped="multipart/form-data" , 通常⽤于提交图 ⽚/⽂件. 对应 Content-Type: multipart/form-data

3>.x-www-form-urlencoded
form表单, 对应 Content-Type: application/x-www-from-urlencoded

4>.raw
可以传任意类型的文本.可以上传text、json、xml、html等

四.传参类型
1>.传递单个参数:

Postman测试:

也可以通过浏览器访问:
后端正确获取到了参数,spring MVC会根据方法的参数名,将参数进行赋值;若传入的参数不匹配,后端是无法获取到参数的。

注意:使用基本类型传参时,参数必须传,否则会报错,boolean除外。
类型不匹配时,会报400错误:

Postman:

未传参数时,会报500错误:

通过idea日志,可以看到错误:

int类型的参数 虽然为可选的, 但由于被声明为基本类型⽽不能转换为空值.(错误原因)
考虑将其声明为对 应基本类型的包装类型.(解决方法)
所以企业开发中,对于参数可能为空的数据,建议使⽤包装类型.
2>.传递多个参数
和传递单个参数一样,直接使用方法的形参接收即可,传递多个参数:

Posrtman:

当传递多个参数时,后端是根据 参数名进行匹配的, 和传递的顺序没有关系.
3>.传递对象
当传递的参数较多时,为了代码美观且方便修改,可以通过 传递对象 的方法进行传参.
创建user类,并重写实现toString方法.

userContro传入user对象

Postman:

后端正确接收到对象的值, spring会根据参数的名称,正确绑定到对象的属性上,若参数为空,spring会赋值为null值;当对象的参数类型为基本类型时,若为空,spring也会将其赋为null,因为对象会自动进行拆包和组包工作.
4>.传递数组
springMVC可以自动绑定数组参数的赋值.

Postman:

可以看到,后端对数组进行了正常的获取和响应.
若通过浏览器访问, 访问路径可以为:
127.0.0.1:8080/user/test07?array=zahngsan&array=lisi&array=wangwu
或: http://127.0.0.1:8080/user/test07?array=zhangsan,lisi,wangwu
或者:http://127.0.0.1:8080/user/test07?array=zhangsan%2clisi%2cwangwu
%2c是逗号的转义字符, 都可以正常访问.
5>.传递集合
参数集合和数组类似,当需要传递多个同名参数时,需要对集合参数 添加@RequestParam注解.
默认情况下,请求中参数名相同的多个值,是封装到数组.如果要封装到集合,要使⽤ @RequestParam 绑定参数关系。

Postman:

通过浏览器访问路径和数组参数路径访问方式相同.
6>.传递JSON数据
JSON:JavaScript Object Notation【JavaScript 对象表⽰法】
JSON是一种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息.
JSON本质是一个字符串,负责进行不同语言中数据的传递和转换.
就类似于中国有56个民族,每个民族都有自己的方言,但有规定的通用语言:普通话。
JSON和javascript 没有关系,js是上手比较快,语法较为简单,比较好学。
JSON语法:
JSON是一串字符串,和javascript对象字面量的格式类似.
JSON语法:
数据在键值对中(key:value);
数据之间有逗号 , 分隔;
对象用 {} 表示;
数组用 [] 表示;
值可以为对象,也可以为数组,数组中还可以包含对象;
JSON数据:

JSON和java格式的转换:
springMVC已经继承了JSON的转换工具,可以直接使用,完成JSON字符串和java对象的数据转换.
如果脱离SpringMVC使⽤, 需要引⼊相关依赖,jackson-databind包
JSON数据的优点:
-
简单易⽤: 语法简单,易于理解和编写,可以快速地进⾏数据交换
-
跨平台⽀持: JSON可以被多种编程语⾔解析和⽣成,可以在不同的平台和语⾔之间进⾏数据交换和 传输
-
轻量级:相较于XML格式,JSON数据格式更加轻量级,传输数据时占⽤带宽较⼩,可以提⾼数据传输 速度
-
易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤ 5. 安全性:JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码,不会执⾏恶意代码,因此具有较⾼ 的安全性
发送JSON请求:
接收JSON 对象 ,需要使用@RequestBody注解.
RequestBody:请求正文,意思是这个注解作用在请求正文的数据绑定,请求参数必须写在请求正文中.

使用Postman发送JSON请求:

当去掉@RequestBody时:

返回的结果都为空值, 后端未能匹配成功.
7>.获取URL中的参数@PathVariable
PathVariable : 路径变量,这个注解主要作用在请求URL路径上的数据绑定.
默认传递参数写在URL路径上,springMVC就可以获取到.

Postaman:
发送请求路径 :127.0.0.1:8080/user/test1/111/zhangsan

浏览器访问:

springmvc正确获取到了参数.
如果⽅法参数名称和需要绑定的URL中的变量名称⼀致时,可以简写,不⽤给@PathVariable的属性赋 值,如上述例⼦中的id变量
如果⽅法参数名称和需要绑定的URL中的变量名称不⼀致时,需要@PathVariable的属性value赋值, 如上述例⼦中的userName变量.
8>.上传文件@RequestPart


后端参数重命名(后端参数映射)
在某些特殊情况下,前端传递的参数key和后端的参数key 可以不一致.
⽐如前端传递了⼀个 time 给后端,⽽后端是使⽤ createtime 字段来接收的,这样就会出现参数接收不到的情况,如果出现 这种情况,可以使用**@RequestParam 来重命名后端的参数值.**


spring可以正确的将前端传入的time参数 绑定到后端的createtime参数上.
当前端使用createtime进行传参时:

报了400错误,idea日志查看:

方法参数类型String不存在所需的请求参数'time'。
若对参数重命名后,前端不能传后端参数的名字,必须传递规定的名字.
对象重命名时,当未传参数时:

还是400错误.
因此,使用@RequestParam将参数重命名后,请求参数必须和@RequestParam声明的参数名一致,才能进行参数绑定和赋值;重命名后,参数就变成了必传参数,若不传参,将会报错。
必传参数和非必传参数
当后端需要对一些参数进行重命名,且是非必传参数时,就需要对@RequestParam注解进行设置,
看一下@RequestParam源代码:

required()方法的默认为true,表示被@RequestParam注解修饰的参数默认为必传参数.
当需要将参数设置为非必传参数时,可以通过设置@RequestParam的required=false来避免不传递时的报错.

当添加required=false时,time前面的key也要加上:value="time".
注解属性赋值时,若没有指明key时,默认为value属性.当要对多个属性赋值时,要加上key.
五.获取request信息
1.获取Cookie/Session
http协议本身属于无状态协议,
**"无状态"**指的是没有记忆性,默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信,和下次通信之间没有直接的联系.
虽然无状态在网络传输过程中是有利的, 但很多时候是需要知道请求之间的关联关系.
例如登录成功后,第二次登录的时候就知道该请求是否登陆过了.
"令牌"

上述传输过程中的"令牌"就存储在Cookie中.
此时服务器就需要记录"令牌"的信息,以及令牌对应的用户信息.这就是Session的工作.
Session:
会话, 对话的意思.
在计算机领域, 会话是⼀个客⼾与服务器之间的不中断的请求响应. 对客⼾的每个请求,服务器能够识 别出请求来⾃于同⼀个客⼾.
当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话. 当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.
服务器同⼀时刻收到的请求是很多的. 服务器需要清楚的区分每个请求是从属于哪个⽤⼾, 也就是属于 哪个会话, 就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.
Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.
Session的本质就是⼀个"哈希表",存储了⼀些键值对结构. Key 就是SessionID, Value就是⽤⼾信息
客户端获取SessionID如下:
用户首次登录的时候,服务器在Session中新增一条记录,并把SessionId返回给客户端(通过HTTP响应中的Set-Cookie字段);
客户端后续再向服务器发送请求的时候,会带上SessionID(通过HTTP请求中的Cookie字段);
服务器接收到请求后,根据SessionID查找Session信息,获取到用户的信息,再进行后续的操作;若没有找到SessionID.则重新创建Session,并给客户端返回SessionID.

注意**:Session数据默认是保存到内存中的,若重启服务器,Session数据会丢失.**
Cookie和Session的区别:
1>.Cookie是客户端保存用户信息的一种机制,Session是服务端保存用户信息的一种机制.
2>.Cookie和Session通过SessionID进行联系.
3>.Cookie和Session经常一起使用,但不是绝对的.
完全可以⽤ Cookie 来保存⼀些数据在客⼾端. 这些数据不⼀定是⽤⼾⾝份信息, 也不⼀定是 SessionId
Session 中的sessionId 也不需要⾮得通过 Cookie/Set-Cookie 传递, ⽐如通过URL传递
获取Cookie:
传统获取Cookie方法:

Postman:

没有获取到任何信息,当前Cookie为空,对Cookie进行设置一下.
SpringMVC是在servlet API的基础上构建的原始web框架,也是在servlet基础上实现的.
HttpServletRequest和 HttpServletResponse是servlet提供的两个类,是Spring的内置对象,使用时直接在方法中添加声明就行.
HttpServletRequest对象****代表客户端的请求,当客户端向服务器发送HTTP请求的时候,HTTP请求头中的所有信息都封装在HttpServletReqest对象中.通过这个对象提供的方法,可以获取HTTP请求头的所有信息.
HttpServletResponse对象****代表服务器返回的响应,HTTP响应的信息都封装在HttpServletResponse对象中.通过这个对象提供的方法,可以获取 服务器响应的所有信息.
SpringMVC对这两个方法进行了封装,更方便使用.
在浏览器中,点击右键->检查,选择Application,对Cookie进行手动添加:

这里也能发现,Cookie是可以修改的,也就意味着可以伪造,因此在后续应用中要对Cookie进行校验.
简洁获取Cookie方法:

获取Session:
Session是服务器端的机制 ,需要先存储,才能获取.
Session也是基于HttpServletRequest来存储和获取的.
Session存储:


void setAttribute(String name, Object value) 方法 : 使用指定的名称绑定一个对象到Session会话上.
通过fiddler转包,可以看到:

获取Session:
获取Session有两种方法:
HttpSession getSession(boolean create);
HttpSession getSession();
HttpSession getSession(boolean create) : 这个方法中传入一个boolean参数若为true,则当Session不存在时,也会创建HttpSession对象;若传入的boolean为false,当Session不存在时,不会创建HttpSession对象.
HttpSession getSession(): 这个方法默认创建httpSession 对象,和getSession(true)效果一样;

Object getAttribute(String name): 获取Session会话中指定名称的对象,若没有指定名称的对象,返回null.
通过fiddler转包,观察请求和响应:

可以看到,http把SessionID请求通过Cookie传送到了服务器.
通过浏览器访问:

通过控制台,可以看到对应值:
简洁获取Session(通过封装进行):
法一:通过@SessionAttribute注解


法二:通过springMVC内置的httpSession对象获取:


注意:
每次重新启动Spring后,在获取Session之前,都要先访问一下设置Session的方法,就是要先设置Session,获取时才能获取到, 因为Session都是存储在内存中的,当重启Spring后,原来的信息都不存在了.
2.获取header:
获取header也是通过HttpServletRequest对象获取的,
使用HttpServletRequestt提供的getHeader()方法,获取,参数传入Http请求对应的"key"

这些都是header的值,通过"key",获取到对应的值.
这里获取"Uaer-Agent":


通过fiddler抓包,观察请求中的User-Agent,和响应结果:

简洁获取header:
通过@RequestHeader()注解获取


六.响应设置
1.返回静态页面
1.创建前端页面:index.html
前端代码在resource.static 文件夹中创建.

在static文件夹中写的都可以以该目录为根目录,直接访问,就能访问到.

当前访问方式是直接通过Http协议直接访问的前端代码,若通过后端进行访问,
后端代码:

此时访问http://127.0.0.1:8080/resp/test01:

是以文字的形式返回的,并没有返回html页面.
这是因为注解的问题,修改注解:

再次访问原路径:

可以看到, 仅对后端代码的@RestController注解改为@Controller注解时,再次访问原来路径,显示的就是html页面.
这是@RestControllerh和@Controller注解的不同功能:
@RestController:
这个注解属于"复合注解",是@Controller + @ResponseBody 两个注解构成
@RestController源码:

@Target:当前注解作用范围 TYPE:表示作用在类上,METHODS:表示作用在方法上
该注解为类注解,只能作用在类上
@Retention:注解的生命周期.有源码周期,编译周期,和运行周期.

该注解的生命周期到运行周期.
@Document: 文档
这三个属于元注解,对该注解的功能上,不起什么作用.
@Controller: 默认返回视图.
@ResponseBody: 默认返回数据.
由于@RestController注解带有@ResponseBody注解,因此,在上面中,后端用@RestController注解访问时,返回的是文本格式,而不是页面.
@Controller:
定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理.
@Controller源代码:

该注解属于类注解,仅能作用在类上。
由于当前业务大多都是前后端分离的,因此,MVC概念也发生了变化,view不再是返回视图,而是返回显⽰视图时需要的数据. 所以前⾯使⽤的 @RestController 其实是返回的数据
@ResponseBody:
定义返回的数据格式为⾮视图, 返回⼀个 text/html 信息
@ResponseBody源代码:

该注解即时类注解,也是方法注解.
作用在类上时,相当于类中的所有方法都加了该注解;作用在方法上,仅对该方法起作用.
若想让返回视图,对类@Controller注解就行。若某个方法需要返回数据,在该类上加上@ResponseBody注解就可以了。
若用@Controller注解,返回的是一个非页面代码会怎样?

浏览器访问test02:

返回404,由于使用的注解为@Controller,程序会认为返回的是视图,根据内容去查找路径 ,但路径不存在,就会报错.
若想让返回的是数据,仅需在代码上加上@ResponseBody注解就可以了:

再次让浏览器访问原路径:

这次返回的就是数据了.
返回html代码:

浏览器访问:

在@ResponseBody注解存在的情况下,返回的还是视图,是因为,程序会对代码进行解析,
通过fiddler抓包,可以看到返回的底层结果为Html文本:

像test01代码,通过fiddler观察响应底层结果:

也是html文件,因此,后端返回数据时,若数据中有Html文件,也会被浏览器解析.
返回JSON代码:
springmvc 也可以返回JSON代码:
是通过对象返回的.

浏览器访问:

通过fiddler抓包,,观察响应结果类型:

可以看到,返回类型Content-Type为 json类型.
因此,程序会根据代码返回类型,自己识别并进行转换为对应类型.
设置状态码:
我们可以自己设置响应的状态码,不会影响到程序的原有状态.
通过HttpServletResponse对象,设置状态码:

浏览器访问:

通过fiddler抓包观察状态码:

设置响应的Header:
相应数据的header也可以对其进行设置:
通过**@RequestMapping注解来实现,**
@RequestMapping源代码:

这个注解既是类注解,又是方法注解.可以修饰类也可以修饰方法.
value/path方法: 都是映射的路径URL,
method方法: 指定请求的method类型:get/post...
params方法: 指定请求中必须包含某些指定的参数才让该方法处理
headers方法: 指定请求中必须包含指定的header值,才让该方法处理
consum e: 指定处理请求的提交的内容类型
produces:指定返回的内容类型.仅当request请求头中的(Accept)类型中包含该指定类型才返回
设置Content-Type:
通过设置 produces属性的值, 设置响应的报头Content-Type
将响应结果设置成json格式:

浏览器访问结果:

通过fiddler抓包观察响应结果的Content-Type类型,为json

若不设置produces,响应结果的Content-Type为字符串

fiddler抓包观察响应结果:

其他header的设置:
要使用spingmvc内置的HttpServletResponse对象中的方法来设置:

通过fiddler观察响应状态:
