目录
1.MVC的定义
MVC是Model View Controller的缩写,是软件工程的一种软件架构设计模式,它把软件系统分为模型、视图、控制器三个基本部分,如下图所示:
对于MVC,在集成开发环境idea中同样封装有,具体使用方式是依靠注解的形式来使用。
在讲解springMVC之前,我们需要了解一下浏览器和服务器是如何进行交互的。
使用浏览器来对服务器发送请求,我们就需要了解URL的相对格式,如拿京东搜索商品举例:
对于本机的ip可以使用localhost或者127.0.0.1,运行本机web端的端口号使用8080。
浏览器和服务器的交互基本如下:
在本机,我们可以利用postman来模拟发送请求,并且关注每个注释不同的用法。
2.SpringMVC的实际应用
(1)建立连接
在idea中创建好spring框架,加载meven项目,会发现main文件夹路径下会有一DemoApplication类,也就是项目的启动类:
@SpringBootApplication这个注释在哪,也就说明该项目的启动入口在哪里。
在springMVC中,常用@RequestMapping来实现URL的映射,使浏览器连接程序。实验期间,我们也需要使用@RestController,使返回对象以http响应体返回。
1.@RequestMapping注解介绍
@RequestMapping注解既可以修饰类,也可以修饰方法。当修饰类和方法时访问的地址是类路径+方法路径,例如:
可以看见,网址以类路径+方法路径的形式输入,不论类路径还是方法路径都可以进行分层,也可以不需要类路径单独访问方法:
2.@RequestMapping注解的请求方式
对于请求,我们有很多种方式可以模拟,比如form表单、postman模拟发送请求。那对于@RequestMapping究竟是get请求还是post请求呢?
GET请求:
浏览器发送的请求类型都是get,说明支持get请求
POST请求:
form表单发送:
将前端代码放入static目录下,访问路径为:127.0.0.1:8080/(html文件名)
点击提交:
指定GET/POST方法类型:
对于@RequestMapping,都支持GET和POST请求,也可以指定接收固定请求
也可以单独使用@PostMapping
这样就只能允许POST请求通过,其他请求不能通过
(2)请求
在测试实验过程中因为模拟请求而屡次创建修改前端代码会显得很麻烦,所以接下来我们将使用postman来完成模拟请求的任务。
首先我们来看看@RequestMapping的内部结构:
传递参数
访问不同路径,就是发送不同的请求,可能会带上一些参数,究竟如何传递参数?后端如何接收参数?
对于框架中的传参,都是以Key-Value的形式来存储的,下面我们以postman来作为请求模拟,学习如何传递参数。
1.传递单个参数
在查询字符串段中以键值对的形式输入数据,就可以完成传参,也可以在postman下方的Params直接输入键和对应的值即可。
2.传递多个参数
和传递单个参数基本一致,也是以键值对的形式输入,不同的是传参顺序可以随意(当有多个参数时前后端匹配是以键值对的形式,位置不受影响),参数类型必须一致!
3.传递对象
当需要传递的参数很多时,为了防止代码冗余难以修改,我们可以封装一个对象,传递该对象的所有参数。
我们先创建出来一个person对象,包含三个属性:
本质上和传递多个参数没什么区别,只是因为这些参数封装成一个对象:
若是该对象内的属性没有输入值,则会分配默认值。
4.后端参数重命名
在有些特殊情况下,前端传递的参数Key可能跟我们后端的Key不一致,容易出现接收不到的情况,这时我们可以使用@RequestParam来重命名解决后端的参数值(后端参数映射)。
需要注意的是,使用了@RequestParam,参数就变成了必传参数!
若是真不想传参数,可以使用required属性至为false,这样就变成可传可不传了。
5.传递数组
SpringMVC可以实现自动绑定数组参数的赋值
6.传递集合
和数组传递类似,但是需要使用@RequestParam绑定参数关系:
7.传递JSON对象
我们先来看json的格式要求:
我们发送JSON数据的时候,再后端可以使用对象接收,使用@RequestBody这个注释进行json数据的转换,在postman上也使用json数据发送,比如使用之前创建的Person类接收:
对于@RequestBody这个注释,主要功能是将HTTP请求体中的数据(JSON,XML)反序列化为java对象。
对于JSON,我们还有更复杂的表示方式:
在上面的JSON数据中包含着对象嵌套数组或者数组嵌套对象这类比较复杂的数据。
通过抓包软件也可以看到json数据:
8.获取URL中参数@PathVariable
在前后端交互中,有时候我们需要获取到URL上面的参数,比如搜索信息的时候获取该URL上面的序列号将对应的网页上传给前端,以便客户查找到对应的信息:
这时候就可以获取URL上面的年份日期或者序列号,将对应的网页上传给客户。
对于获取URL的参数我们使用的是@PathVariable注解,主要作用在请求URL路径上的数据绑定。
注意的是,在RequestMapping上待定参数用{}号框起来:
9.上传文件@RequestPart
对于文件,我们可以使用@RequestPart注解来传输,比如我们将一张照片传输到D盘的temp文件上:
可以看到,文件已经传输成功了。
10.获取Cookie/Session
首先我们要知道,HTTP协议自身是属于“无状态”协议,默认情况下HTTP的客户端和服务器之间的这次通信,和下次通信之间没有直接的联系。
但是在实际开发中我们很多时候是需要这些联系的,例如浏览器登录成功的时候,第二次访问服务器就知道该请求是否已经登录过了。
介绍Cookie&Session:
下面以医院挂号的例子说明一下Cookie和Session机制:
对于Cookie和Session,还可以这样理解,还是以上述为例:
对于Cookie而言,存取少量信息,包含关键的唯一性字符串,也就是SessionId。
对于Session而言,本质上就是一个“哈希表”,存储了一些键值对结构,Key就是SessionID,Value就是用来标识的用户信息(灵活转换)。
Cookie和Session的区别
1.Cookie是客户端保存用户信息的一种机制,Session是服务端保存用户信息的一种机制
2.SessionId是Cookie和Session之间的桥梁
3.Cookie和Session经常一起使用,但不是必要:
完全可以用Cookie来报错一些数据在客户端,这些数据不一定是用户身份信息或者SessionId
Session中的sessionId也可以使用URL传递
获取Cookie
在此之前,我们先回顾一下http请求的格式,使用fiddler来抓包:
以POST请求为例,在请求中有许多信息,比如URL,请求方式,header,body等参数,响应中也有http状态码,响应header和响应正文等信息,我们要是想获取这些参数,就需要知道俩个对象,这俩对象是Servlet提供的俩个类,是Spring的内置对象:
HttpServletRequest(客户端请求):当客户端通过HTTP访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象的方法可以获取到请求的所有信息。
HttpServletResponse(服务端响应):同理,HTTP的响应信息都在这个对象中,响应头状态码等,通过这个对象的方法可以获取到服务器响应的所有信息。
一般获取Cookie:
代码解析:
postman设置Cookie值:
最后设置成功:
浏览器设置Cookie值:
简洁获取Cookie:
使用@CookieValue注解
获取Session
Session是服务器的机制,我们需要先存储,才能再获取,对于Session也是基于HttpServletRequest来存储和获取的。
一般的Session内部大概是这样的:
Session存储
代码演示:
然后我们使用postman来发送请求:
我们看看fiddler抓包结果:
可以看到,正如上面所说,Cookie和Session是通过SessionID建立联系,创建Session之后通过Set-Cookie告知客户端并把SessionID储存在Cookie中。
通过浏览器也可以观察SessionID:
我们也可以直接省略掉HttpServletRequest使用HttpSession:
Session获取
获取Session我们依旧可以使用HttpServletRequest:
简洁获取Session(1)
需要使用到@SessionAttribute注解
简洁获取Session(2)
通过Spring内置对象HttpSession来获取(省略HttpServletRequest)
获取Header
对于header,我们随机抓一个包来看看:
获取header也是从HttpServletRequest中获取的。
对于获取user-Agent,我们可以采取以下方法:
一般获取Header
同过抓包软件我们也可以看到user-Agent:
简洁获取Header
该方法用到@RequestHeader注释
这回我们使用浏览器浏览:
查看抓包软件:
(3)响应
对于响应来说,我们前面涉及的都是数据响应,HTTP响应还能响应静态页面。在讲解响应之前我们先来回顾上面所说到的@RestController注释:
@RestController是一个组合注解,它结合了@Controller+@ResponseBody的功能,我们可以看看内部:
RestController和Controller注解:
之前我们使用的@RestController是把数据直接写入到http响应体上,不能直接跳转到某个页面上,这是因为该注解中有一个@ResponseBody,如果我们单纯使用@Controller,就会发现可以跳转页面了,再对比使用@RestController:
我们先创建一个html文件:
@RestController:
@Controller:
返回数据@ResponseBody:
由上面的俩个不一样的注解我们可以看到,加上了@ResponseBody的注释的返回值是返回数据到响应体,而没有加上的@Controller则是直接跳转到某页面上,但是需要注意的是:对于返回页面我们需要在文件前面加上“/”,不像是@RequestMapping一般,加不加都有校验的地方,这是硬性要求。
对于@ResponseBody,它既是类注解也是方法注解,作用于类上,代表该类的所有方法都是返回数据,作用于方法上代表该方法返回的是数据。
@Controller+@ResponseBody:
返回HTML代码片段:
对于后端返回数据时,数据中有html代码也会被浏览器解析:
为什么会这样呢?我们先来看看fiddler抓包结果:
我们再来看几个常见的Content-Type取值:
text/plain :纯文本格式
text/html :body的数据格式是HTML
text/css :body的数据格式是CSS
application/json :body的数据格式是JSON
application/javascript :body的数据格式是JavaScript
http协议会根据请求的文件判断是什么类型的,然后自动设置Content-Type值返回响应。
返回JSON:
我们也可以返回JSON类型的数据,继续延用我们上面创建过的Person类:
http成功将响应数据设置为JSON格式,我们再来看看fiddler抓包:
对于后端返回的结果对象或集合,响应页面自动转为JSON。
我们再来看组集合的返回:
设置Content-Type:
其实不仅仅是依靠http协议来识别转换Content-Type,我们也可以通过设置produces属性的值来设置响应的报头Content-Type。
我们先来看一个例子:
可以看到,由于返回类型是String类型,默认为字符串,所以http响应默认转换为html的格式。
我们要想让这个字符串变成JSON格式,需要利用@RequestMapping注解的produces属性来转换:
再看看fiddler抓包结果:
设置状态码:
我们之前也了解过状态码了,但是状态码是不是就只能由SpringMVC自己自动设置响应状态码,我们能不能设置响应状态码呢?
答案是可以的,我们可以手动指定状态码,通过SpringMVC的内置对象HttpServletResponse提供的方法设置:
然后我们抓一下包:
发现这里的状态码是404,但是我们的页面还能正常显示:
所以我们得出结论,在这里设置的状态码不影响页面的展示。
设置Header:
对于我们的Http响应报头来说有挺多的附加信息,这些信息可以通过@RequestMapping注解的属性来实现。
对于@RequestMapping注解,我们可以看看内部结构:
我们还可以设置响应的Header属性的值,也需要SpringMVC内置对象HttpServletResponse提供的方法来进行设置:
我们来看看fiddler抓包:
可以看到我们已经设置了Header