什么是SpringWebMVC
Spring Web MVC是基于servlet API构建的原始web框架,从一开始就包含在Spring框架中.他的正式名称为"Spring Web MVC" 但他通常被称为Spring MVC
什么是servlet呢?
servlet是一种动态实现页面的技术,准确的来讲servlet是一套JAVA Web规范,或者说是一套JAVA Web开发的技术标准,只有规范并不能做任何事情,必须有人去实现它 所谓实现servlet规范,就是真正编写代码区实现servlet规范提到的各种功能,包括类,方法,属性等
从上述对SpringWebMVC的定义我们可以得出一个信息:SpringWebMVC是一个Web框架
什么是MVC
MVC是Model View Controller的缩写,他是软件工程中的一种软件架构设计模式,他把软件系分为模型,视图和控制器三个基本部分

View(视图)指在应用程序中专门用来与浏览器进行交互展示数据的资源
Model(模型)是应用程序的主体部分,用来处理程序中数据逻辑的部分
Controller(控制器)可以理解为一个分发器,用来决定对于视图发来的请求,需要用哪一个模型来处理,以及处理完之后需要跳回到哪一个视图,即用来连接视图和模型
什么是SpringMVC
MVC是一种架构设计模式,也是一种思想,而SpringMVC是对MVC思想的具体实现,除此之外,SpringMVC还是一个Web框架 总结来说:SpringMVC是一个实现了MVC模式的Web框架
Spring MVC主要关注两个点:1.MVC 2.Web框架

学习Spring MVC
SpringMVC是一个Web框架,那么当用户在浏览器输入了url之后,我们的SpringMVC项目就可以感知到用户的请求,并且给予相应
我们学习SpringMVC重点也就是如何通过浏览器和用户程序进行交互
主要分为以下三个方面:
1.建立连接:将用户(浏览器)和JAVA程序连接起来,也就是访问一个地址能够调用到我们的Spring程序
2.请求:用户请求的时候有时会带一些参数,在程序中要想办法获取到参数,所以请求这块主要是获取参数的功能
3.响应:执行了业务逻辑之后,要把程序执行的结果返回给用户,也就是响应
对应SpringMVC来说,掌握了上述三个功能就相当于掌握了SpringMVC
项目准备:SpringMVC项目创建和SpringBoot创建项目相同,在创建的时候选择SpringWeb就相当于创建了SpringMVC项目
建立连接
在SpringMVC中使用@RequestMapping来实现URL路由映射,也就是浏览器连接程序的作用
java
@RequestMapping("/user")
@RestController
public class UserController {
@RequestMapping("/m1")
public String m1(){
return "m1";
}
}
资源路径要保证唯一 资源路径:类路径+方法路径
上述代码中"/user"是类路径 "/m1"是方法路径 这里我们建议给所有的类加上类路径,有两个好处:1.增强了可读性 2.避免发生错误
这里我们对@RequestMapping进行介绍
@RequestMapping既可修饰类,也可修饰方法,当修饰类和方法的时候,访问的地址是类路径_方法路径
@RequestMapping既支持post也支持get
我们也可以在@RequestMapping中指定参数让他只能支持get/post方法(这里也可以是其他方法,但由于主要的方法是get/post 所以我们主要讲这个)
java
//只支持get == @GetMapping
@RequestMapping(value = "/m2",method = RequestMethod.GET)
public String m2(){
return "m2";
}
//只支持post == @PostMapping
@RequestMapping(value = "/m3",method = RequestMethod.POST)
public String m3(){
return "m3";
}
请求
访问不同的路径,就是发送不同的请求,在发送请求时,可能会带一些参数,所以学习Spring请求,主要是学习如何传递参数到后端以及后端如何接受
传递参数,我们主要使用的是浏览器和postman来模拟
使用postman发送请求和客户端发送请求,对于后端而言,是一样的
1.传递单个参数
接受单个参数,在SpringMVC中直接用方法中的参数就可以
springmvc 会根据方法的参数名,找到对应的参数,赋值给方法(这里要注意方法中的变量名要和传递的参数名称保持一致)
2.传递多个参数
接受多个参数和接受单个参数是一样的,直接使用方法的形参接受即可,使用多个形参
3.传递对象
如果传递的参数比较多是,我们可以把这些参数封装成一个对象,这样后续如果修改参数也不要修改方法声明
这里注意Spring会根据参数名称自动绑定到对象的各个属性上,如果某个属性未传递,则赋值为null(基本类型则默认初始值,比如int类型的属性,会被赋值为0)
4.后端参数重命名(后端参数映射)
某些特殊情况下,前端传递的参数和我们后端接受的参数可以不一样 这样就会出现参数接受不到的情况,如果出现了这样的情况,我们可以使用@RequestParam来重命名前后端的参数值
使用@RequestParam进行参数重命名时,请求参数只能和@RequestParam声明的名称一致,才能进行参数绑定和赋值
使用@RequestParam进行参数重命名时,参数就变成了必传参数
非必传参数设置
如果我们的实际业务前端的参数是一个非必传的参数,针对上述问题,如何解决呢?
我们先来了解一下参数必传的原因,我们查看@RequestParam注解实现就可以发现问题
\
我们可以看到required的默认值是true,表示的含义就是该注解修饰的参数默认为必传
那么我们就可以通过设置@RequestParam中的required=false来避免不传递时的报错
5.传递数组
SpringMVC可以自动绑定数组参数的赋值
6.传递集合
集合参数:和数组类似,同一个请求参数名有多个,且需要使用@RequestParam绑定参数关系
默认情况下,请求中参数名相同的多个值,是封装到数组,如果要封装到集合,要使用@RequestParam绑定参数关系
7.传递JSON数据
什么是JSON: JavaScript Object Notation[JavaScript 对象表示法]
JSON是一种数据格式,有自己的格式和语法,使用文本表示一个对象或者数组的信息,因此,JSON本质上就是字符串,主要负责在不同的语言中数据传递和交换
JSON的语法:
1.数据在键值对(key/Value)中
2.数据由逗号分割
3.对象用{}表示
4.数组用[] 表示
5.值可以为对象,也可以为数组,数组中可以包含多个对象
JSON的两种结构:1.对象:大括号{}保存的对象是一个无序的键值对集合,一个对象以左括号{ 开始,右括号}结束 每个键后跟一个冒号,键值对用逗号分割
2.数组:中括号[] 保存的数组是值的有序集合,一个数组以左中括号开始,右中括号结束,值之间使用逗号分割
常见的json和对象转换工具:1.gson 2.fastjson 3.jackson
使用objectMapper.writeValueAsString(对象名) 可以将对象转为JSON字符串
JSON字符串也可以使用objectMapper.readValue(json,类.class)转换为对象
传递JSON对象
接受JSON对象,需要使用@RequestBody注解
8.获取URL中参数@PathVariable
path variable:路径变量,和字母表达的意思一样,这个注解的主要作用在请求URL路径上的数据绑定
9.上传文件@RequestPart
HTTP RequestParam参数可以放在1.url的资源路径 2.url的查询字符串 3.header 4.body
路径参数:url除去查询字符串
请求参数:url的查询字符串和正文
10.获取cookie和session
Cookie和Session的最大的区别:Cookie存在客户端上 Session存在服务器上
HTTP协议自身是属于无状态的协议,(无状态是值默认情况下,HTTP协议的客户端和服务器之间的这次通信和下次通信之间无直接的练习),但实际开发中,我们很多时候都需要知道请求之间的关联关系(例如登录网站成功之后,第二次访问的时候服务器就能知道该请求已经登录过了)

上述的令牌通常存储在Cookie中,Cookie中会存储sessionID
什么是session
session是服务器为了保存用户信息而创建的一个特殊的对象
Session本质上是一个哈希表,存储了一些键值对结构,key就是SessionID,Value就是用户信息(用户信息可以根据需求进行灵活设计)
SessionID是由服务器生成的一个"唯一性字符串",从Session机制的角度来看,这个唯一性字符串称为"SessionID" 但是站在整个登录流程中看,也可以把这个唯一性字符串称为token

Session默认是保存在内存中的,如果重启服务器则Session数据丢失
Cookie和Session的区别:1.Cookie是客户端保存用户信息的一种机制,Session是服务器端保存用户信息的一种机制 2.Cookie和Session之间主要是通过SessionID关联起来的,SessionID是Cookie和Session之间的桥梁
3.Cookie和Session经常会在一起配合使用,但不是必须配合
获取Cookie有两种方式
1.HttpServletRequest
java
@RequestMapping("/r3")
public String r3(HttpServletRequest request, HttpServletResponse response){
Cookie[] cookies = request.getCookies();
StringBuilder builder = new StringBuilder();
if(cookies!=null){
for(Cookie ck :cookies){
builder.append(ck.getName()+" "+ck.getValue());
}
}
return "cookie信息: "+builder;
}
2.通过注解获取Cookie
java
@RequestMapping("/r4")
public String r4(@CookieValue("bit") String bit){
return "bit "+bit;
}
获取session
session的存储和获取
Session是服务端的机制,我们需要先存储,才能再获取
Session也是基于httpServletRequest来存储和获取的
Session存储
java
@RequestMapping("/setSess")
public String setSess(HttpServletRequest request){
HttpSession session = request.getSession();
if(session!=null){
session.setAttribute("username","july");
}
return "session存储成功";
}
Session获取
这里要注意HttpSession getSession(boolean create) :参数如果未true,则当不存在会话时,会创建新会话,参数如果未false,则当不存在会话时会返回null
java
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request){
HttpSession session = request.getSession(false);
if(session==null){
return "用户未登录";
}else{
String userName = (String) session.getAttribute("userName");
return "登录用户为: "+userName;
}
}
@RequestMapping("/getSession2")
public String getSession2(HttpSession session){
if(session==null){
return "用户未登录";
}else{
String userName = (String) session.getAttribute("userName");
return "登录用户为: "+userName;
}
}
@RequestMapping("/getSession3")
public String getSession3(@SessionAttribute("userName") String userName){
return "登录用户为: "+userName;
}
11.获取header
传统获取header
获取header也是从HttpServletRequest中获取
html
@RequestMapping("/param10")
public String param10(HttpServletRequest request,HttpServletResponse response){
String userAgent = request.getHeader("User-Agent");
return userAgent;
}
简洁获取header
@RequestHeader("key的名字")
响应
在我们前面的代码例子中,都已经设置了响应数据,HTTP响应结果可以是数据,也可以是静态页面,也可以针对响应设置状态码,Header信息等
1.返回前端页面
创建前端页面,应该放在Resources的static里面

java
@RestController
public class IndexController {
@RequestMapping("/index")
public Object index(){
return "/index.html";
}
}
结果却发现,页面未正确返回,HTTP响应把"/index.html"当做了http响应正文的数据
那SpringMVC如何才能识别出来index.html是一个静态页面并进行返回呢?
我们需要把@RestController改为@Controller
java
@Controller
public class IndexController {
@RequestMapping("/index")
public Object index(){
return "/index.html";
}
}
再次运行结果,发现页面被正确展示了
@RestController和@Controller有着什么样的关联和区别呢?
我们前面讲了MVC模式,后端会返回视图,这是早期的概念
随着互联网的发展,目前项目开发流行"前后端分离"的模式,JAVA主要是用来做后端项目的开发,所以也就不再处理前端相关的内容了
MVC的概念也就逐渐发生了变化,View也就不再返回视图,而是返回显示视图时所需的数据
所以前面使用的@RestController其实返回的是数据
@RestController = @Controller + @ResponseBody
如果既有返回页面的方法,又有返回数据的方法,使用@Controller 在返回数据的方法上加@ResponseBody
如果一个类全部返回数据可以使用@RestController /@Controller +@ResponseBody
@ResponseBody既是类注解,又是方法注解
作为类注解的时候,表示该类的所有方法全部返回数据
作为方法数据的时候,表示该方法返回数据
2.返回HTML代码片段
后端返回数据时,如果数据中有HTML代码,也会被浏览器解析
java
@RequestMapping("/returnHtml")
@ResponseBody
public String returnHtml(){
return "<h1> hello,html~</h1>";
}

通过fiddler观察响应结果,Content-Type为text/html

响应中的Content-Type常见的取值有以下几种:
1.text/html:body数据格式是HTML
2.text/css:body数据格式是CSS
3.application/javascript: body数据格式是JavaScript
4.application/json:body数据格式是JSON
如果请求的是js文件,SpringMVC会自动设置Content-Type为application/javascript
java
@RequestMapping("/index2")
public Object index2(){
return "/a.js";
}

如果请求的是css文件,SpringMVC会自动设置Content-Type为text/css
java
@RequestMapping("/index3")
public Object index3(){
return "/b.css";
}
3.返回JSON
SpringMVC也可以返回JSON
4.设置状态码
状态码不会影响页面的展示
java
@RequestMapping(value = "/setStatus")
@ResponseBody
public String setStatus(HttpServletResponse response){
response.setStatus(401);
return "设置状态码成功";
}


5.设置header
http响应报头也会向客户端传递一些附加信息,比如说服务程序的名称,请求的资源已经移动到新的地址等.如:Content-Type,Local等
这些信息通过@RequestMapping注解的属性来实现

1.value:指定映射的URL
2.method:指定请求的method类型,如GET/POST等
3.consumes:指定处理请求的(request)的提交内容类型(Content-Type)
4.produces:指定返回的内容类型,还可以同时设置返回值的字符编码
5.Params:指定request中必须包含某些参数值时,才让该方法处理
6.headers:指定request中必须包含某些指定的header值,才能让该方法处理请求


