一、Spring MVC
spring的启动类
启动类是看这个 @SpringBootApplication 注解,而不是 类的名字
这个注解在哪,哪个类就是启动类
1.MVC思想
举例
二、Spring MVC
mvc 是一种思想,而spring mvc是对mvc思想的一种实现。全称是 spring web mvc,基于servlet API 构建的web的框架。
spring mvc看一看作称一个模块,被包含在 spring框架中。
1、建立连接
1)@RequestMapping(“/路径名”):使用这个注解,建立连接
1.1作用域
1.1.1 作用在 方法 上(访问 直接使用 方法路径 即可)
在 demo 包里,创建一个UserController 类,写一个return hello 的方法,在方法前给上 注解 @RequestMapping(‘/hello’)
启动服务器后,发现并没有访问到
原因是,在项目中会有很多个方法,spring不会一个一个检查每一个方法前面是否有 @RequestMapping注解,所以在这里报错了。
在类的前面加上 @RestController
然后就能正常显示了
1.1.2 作用在 类 上(访问路径就成了 类路径+方法路径)
在 user controller类前,加上@RequestMapping 注解
(多个注解之间无优先顺序之分,同时生效)
再用之前的hello路径访问,就没有效果了
此时需要加上 类 的路径,就能成功访问了
访问的路径,可以是多层的
同时在以往servlet 里,路径里的里的第一个 / ,是要加上的。
但是在 spring 里,这第一个 / ,可加可不加,一样是能正常访问的。
建议还是加上。
1.2 请求方式 get 和 post 都支持
使用postman 发送get 和post请求,再用fiddler 抓包
发现 @RequestMapping 这两种方法(get 和post) 都可以
postman的简单介绍
2)指定请求方式
既然 get 和 post 两种方式都支持,那如果有些方法只能通过某种特定的方式访问,不希望通过其他方式访问的时候,就可以指定HTTP请求方式。
指定请求方式:
@RequestMapping(value = “/路径名”,method = RequestMethod.方法名)
在括号里,=左边 为属性名,=右边为属性值,多个属性之间使用逗号隔开
@RequestMapping 里的属性
给注解里,指定HTTP请求方法为 get
重新启动之后
get请求能正常拿到返回值 hello
此时post请求,无法访问了,提示 method not allowed(方法不被允许),就是说请求方式错了。
这也说明了,指定方法get之后,只能通过get访问了
2、发送请求 @RestController
2.1请求
2.1.1 请求单个参数
例子1:
例子2:
假设没有传参进去,会有怎样的效果
服务器错误
5开头错误一般是服务器问题,查看后端日志,找问题
(一段一段看,从后往前看,看每段的第一行)
因为定义方法中参数类型是基本类型 int,所以访问的url不写参数是,默认被当作null空值,发送请求了。
而 null,无法传入到 int 类型中,所以报错了
修改代码,将参数类型改为包装类型 Integer
再次试验
这次就正常响应了
2.1.2 传递多个参数
在接收多个参数时,url地址栏传参的顺序可以变化
只需要保证这里的属性名相同就行
2.1.3 当参数比较多的时候,可以创建一个对象,作为传入参数
例如现在要传递的参数有 Integer id,String name,Integer age
此时创建一个对象 UserInfo
在直接传参时,使用基本数据类型,如果 url里没有写参数,会报错。只能写包装类型。
(2.1.1 请求单个参数 例子2)
而传递的参数是 对象 时,可以使用基本数据类型
当 传递对象的 id 数据类型是 Integer 时,不传id,返回的是null
当把 Integer 修改为 int 基本类型时,不会报错,返回的是 0 (默认值)
2.2 对参数重命名@RequestParam("新名字")
2.2.1 重命名后,用新名字访问,否则报错 400
原本传递的参数名应该是 usernmae,但是修改为 name后
在url地址栏就应该是 name了
使用重命名后的参数名 name 就可以访问了
当使用原来的参数名username访问时,报错 400
2.2.2 重命名后,默认该参数成为必传项,不传会报错 400;也可修改为非必传项 required = false ;
修改 required = false ,就可以不用传这个参数了
修改为非必传项后,不传递该参数,就不会报错了
2.3 请求参数为数组
第一种传递方式:一个参数里有多个值
第二种传递方式:有多个参数名相同的值传递时
2.4 请求参数为 顺序表 List(集合@RequestParam 来绑定参数关系)
发现报错500 ,服务器这边出现问题
查看日志
对于list接口,没有找到构造函数
原因是:spring中规定了,请求中相同参数名的多个值,默认封装到数组。要想封装到集合,需要用 @RequestParam 来绑定参数关系
而这里的请求参数为list,是集合,所以要用 @RequestParam 绑定list
修改代码
发现绑定list之后,能正常访问了
同样的,加上 @RequestParam注解之后,该参数默认就为必传项了,不传会报错
如果想修改为 非必传项,就需要 加上 requeired = false
但是发现 现在又是 500 的错误了,解决完400的错误,现在是服务器端的错误了
查看日志
错误原因,list是null空指针
于是在服务器代码里,添加一个空指针的判断
解决问题了
2.5 传递 JSON 数据
json是一个字符串,key : value这样的键值对,key 只能是字符串(引号引起来的),而value可以是字符串、数字、布尔、数组、list等;多个键值对之间用 都好分隔
对象用{}表示,数组用[]表示,json就是用{}或者[],将键值对包含起来的
在工作中广泛使用
JSON对象的创建
请求 Json 数据 @RequestBody
直接在 Params这里是没有用的,报了400的错误,客户端这边的问题,传递数据的方式有问题
查看日志
发现请求正文没有
重新传递正确Json数据
2.6 请求 URL 中的参数 @PathVariable
常见的网站也可能使用这样的方式,例如CSDN、今日头条
{}里面是定义的路径
2.6.1单个路径变量
2.6.2多个路径变量
要按照这个路径规则访问,才能正常访问 假设不按照规则访问,例如故意将类型为Integer 的 age写成 字符
就会发生错误
2.6.3 同时被 @PathVariable 注解 修饰后,也会变成 必填项
如果不填也会报错
2.6.4 重命名
2.7 上传文件 @RequestPart
2.7.1 获取原始文件名 .getOriginalFilename()
代码中的 MultipartFile 是文件的类型,自定义文件名为 file
在下面这张图测试发送请求的时候, key 也要与这里的 file 对应上
2.7.2 将获取的到的文件,转移到新的目录下 .transferTo
目的路径下找到了该文件
测试了 ,不加注解 @RequestPart 也能正常上传,但是还是建议加上,不然不知道以后会不会有其他的问题。
重命名之后,新的名字newfile 也要与 请求中的 key值 newfile 对应上,否则就会出现以下的错误
正确请求应该是 newfile
2.8 获取 cookie 和 session
2.8.1 cookie和session的概念
cookie和 session
举例:
1.用户提供账号和密码,服务器进行验证
2.服务器验证通过,会把信息存储在session中,并且把 sessionId 返回给客户端(通过set - Cookie 的方式)
3.客户端收到响应,吧sessionID 存储在Cookie中
4.后续的请求中,客户端带着SessionId 去请求(带着 Cookie 信息去请求)
共同点:
都是会话机制
区别:
1.虽然都是保存用户信息的一种机制,但是
cookie是客户端机制
session是服务器机制
2.cookie 和 session 主要是通过 session ID 关联起来的,session ID 是cookie 和 session 之间的桥梁。
3.cookie 和 session 通常是一起出现配合使用的,但不是必须配合。
完全可以用 cookie 来保存一些数据在客户端。这些数据不一定是用户身份信息,也不一定是sessionID。
session 中的 sessionID 也不需要非得通过 Cookie/set-Cookie 传递,比如通过URL 传递。
2.8.2 获取cookie
2.8.2.1 传统方式 servlet 获取 cookie
启动之后,发现报错了
查看日志,发现是空指针问题
修改代码
可以在浏览器设置cookie
再次刷新,成功获取到 cookie了
在日志中可以看到获取的cookie 值,这个就是刚才在浏览器中设置的cookie值
在postman里也可以设置cookie
2.8.2.2 Springboot 获取 cookie (使用注解@CookieValue)
传统的方式 :使用 servlet 获取 cookie 是获取到的所有的 cookie
而 spring boot 只能获取一个 特定的 cookie,使用注解 @CookieValue("对应的cookie名")
现在有两个Cookie
先使用 传统方式 获取所有cookie
在日志里看到了所有的 cookie
再使用 spring boot 的方式 获取 指定的 ameris 这个cookie
获取成功
2.8.3 获取session
2.8.3.1 传统方式获取 session
一开始获取 session 为空
设置 session 的 参数之后
就能成功获取到 session了
2.8.3.2 Spring boot方式获取 session (使用注解 @SessionAttribute)
发现报错了
原因是 加上注解之后,session里面这个 userName属性 变成必传项了,如果不传就会报错
修改代码
2.9 获取 header
2.9.1 传统方式获取 header(HttpServletRequest )
当使用postman发送请求时,获取的User-Agent(用户代理:显示请求时所用的浏览器相关信息)就是 postman
使用谷歌浏览器,响应的就是谷歌浏览器的相关信息
2.9.2 Spring boot方式获取 header(使用注解 @RequestHeader("要获取的字段名"))
总结 请求的几个注解
@RestController 在代码最前面写上,将方法返回的结果直接作为响应内容发送到客户端。(只返回数据,不返回页面)
@RequestMapping("/路径名") 通过URL进行路由映射 。既是类注解,又是方法注解。
访问的URL路径 = 类路径+方法路径
指定请求方式:@RequestMapping(value = “/路径名”,method = RequestMethod.方法名)
@RequestParam(“重命名参数”)和绑定(“绑定集合类型对象比如List”)
@RequestBody 请求Json格式数据
@PathVariable 请求URL 中的变量
@RequestPart 上传文件
获取cookie
传统使用servlet获取所有的cookie,spring使用的是@CookieValue(“cookie”) 获取指定的cookie
获取session
传统使用servlet,spring使用的是@SessionAttribute(“session的字段名”)获取session会话中指定的字段
获取header
传统使用servlet,spring使用的是@RequestHeader(“header的字段名”)获取header会话中指定的字段
3.响应 @Controller
3.1 返回静态页面
先在static包下写一个index页面
在浏览器直接访问这个页面的方法
static目录下的页面,直接写在 “127.0.0.1:端口号/" 后面
如果 static目录下还有文件夹,则需要写上 文件夹名/页面名
写了响应代码,最开始使用@RestController
期望的结果是,响应index这个页面内容
这里的 /index.html中 的 / ,指的是127.0.0.1:端口号
当访问r1时,响应的不是 index页面 ,而是一个字符串
然后将注解改成 @Controller
发现返回了正确的 index页面
3.1.2 @Controller 与 @RestController 的区别
@RestController源码
@Target 指的是使用范围 。TYPE指的是类,METHOD指的是方法。
@Retention 指的是生命周期。
SOURCE:生命周期为编译期间。 CLASS:类中存活。 RUNTIME:代码运行期间。(最长寿)
@Document 指的是一些文档。
前面三个注解是 元注解,就是能给其他注解前面注解。
@Controller 默认返回的是页面
@RestController = @Controller (管理spring中的代码)+ @ResponseBody(仅返回数据本身)
所以在最开始,使用@RestController,原本期望返回index页面,结果只返回了数据本身,也就是 “/index.html” 这个字符串。
在改成@Controller后,就返回的是对应的index.html这个页面了。
3.2 返回数据 (@ResponseBody)
那在@Controller 下只想返回数据本身怎么办?
加上 @ResponseBody 这个注解就好了.
@ResponseBody源码
既能修饰类,也能修饰方法。
修饰类:该类下所有方法,返回的仅仅是数据本身。
修饰方法:该方法返回的仅仅是数据本身。
3.3 返回HTML片段
返回HTML片段,其实就是 HTML标签语言
由于返回的HTML语句本质上还是数据本身,不是页面,所以要写上注解 @ResponseBody
3.4 返回JSON格式、js格式、css格式等
Spring会根据返回的数据类型,自动转换相应的格式。
当返回类型是 对象 时,自动转换为 JSON格式
当返回的是Map,自动转换为 JSON
当返回的是 js 页面,响应时自动转换为 application/javascript
当返回的是css文件时,响应自动转换为 text/css 格式
3.5 设置响应头(状态码,编码,或者其他header)
3.5.1设置响应的状态码
状态码的设置,不影响页面的显示
3.5.2 设置content-type
content-type:默认是 html
指定返回的类型 @RequestMapping(value = "/r9",produces = "application/json")