为什么要学习SpringBoot
- 在SSM中需要写很多的配置才能进行正常的使用
- 实现一个功能需要引入很多依赖,尤其是要自己去维护依赖的版本,容易出现依赖冲突等问题
SpringBoot就能很好的解决上述问题
SpringBoot是什么
Spring是基于Spring开发的全新框架,相当于对Spring做了又一层封装
其设计的目的是用来简化Spring的初始搭建开发过程,该框架使用了特定的方式进行配置,从而使开发人员不需要定义样板化的配置;并且对第三方依赖的添加也进行了封装简化
Spring能做的他都能做,并且简化了配置,并且提供了Spring没有的:
- 内嵌WEB容器,不需要再部署到web容器中
- 提供准备好的特性,如指标、健康检查和外部化配置
最大特点:自动配置、起步依赖
快速入门
基本环境要求
JDK8;Maven3.5
1 | <mirrors> |
HelloWorld
配置父工程
1 | <parent> |
添加依赖
1 | <dependencies> |
创建启动类
@SpringBootApplication注解标识为启动类
1 | package cn.xiaohupao; |
定义Controller
1 | package cn.xiaohupao.controller; |
运行测试是直接运行启动类的main方法
常见问题及解决方案
访问时404
将Controller放在启动类所在的包及其子包下
打包部署
可以把SpringBoot的项目打成jar包直接运行
添加maven插件
1 | <build> |
maven打包
package
运行jar包
在jar包所在的目录执行命令
1 | java -jar jar包名称 |
快速构建
起步依赖
SpringBoot依靠父类项目的版本锁定和starter机制让我们能够更轻松的实现对依赖的管理
依赖冲突及其解决方案
依赖冲突
一般程序在运行时发生类似于java.lang.ClassNotFoundException,Method not found:‘……’ 或者莫名其妙的异常信息,这种情况一般很大可能就是jar包依赖冲突的问题引起的。
一般在A依赖C(低版本),B也依赖C(高版本)。都是他们依赖的又是不同版本的C的时候会出现。
解决方案
如果出现了类似于java.lang.ClassNotFoundException,Method not found这些异常检查相关的依赖冲突问题,排除掉低版本的依赖,留下高版本的依赖
安装Maven Helper插件
版本锁定
SpringBoot模块都需要继承一个父工程:spring-boot-starter-parent。在spring-boot-starter-parent的父工程spring-boot-dependencies中对常用的依赖进行了版本锁定。这样我们在添加依赖时,很多时候不需要添加依赖的版本号。
我们也可以采用覆盖properties配置或者直接指定版本号的方式修改依赖的版本。
starter机制
一个starter针对一种特定的场景,其内部引入了该场景所需的依赖。这样我们就不需要单独引入多个依赖了。
官方starter都是以spring-boot-starter开头后面跟上场景名称
非官方starter都是以场景名-spring-boot-starter的格式
自动配置
SpringBoot中最重要的特性就是自动配置
SpringBoot遵循约定优于配置的原则,自动进行了默认配置。这样我们就不需要做大量的配置。
当我们需要使用什么场景时,就会自动配置这个场景相关的配置
如果他的默认配置不符合我们的需求时修改这部分配置即可
YML配置
YML简介
YAML不是一种标记语言,通常以.yml为后缀的文件,是一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言导入,一种专门用来写配置文件的语言。
YAML试图一种比XML更简洁的方式,来完成XML所完成的任务。
YML优点
- YAML易于人们阅读
- 更加简洁明了
YML语法
约定
K: V表示键值对关系,冒号后面必须有一个空格
字符串默认不用加上单引号或双绰号;双引号,转义符能够起作用;单引号会转义特殊字符,特殊字符最终只是一个普通的字符串数据
```yaml
name1: wk
name2: lsn
age: 18
flag: true1
2
3
4
5
* 日期
* ```yaml
date: 2021/10/25
使用空格的缩进表示层级关系,空格数目不重要,只要是左对齐的一列数据,都是同一层的
大小写敏感
缩进时不允许使用TAB,只允许空格
java中对于驼峰命名,可用原名或使用-代替驼峰,例如:lastName;last-name可完成映射
对象、Map
多行写法:在下一行来写对象的属性和值的关系,注意缩进
1 | student: |
1 | map: |
行内写法:
1 | student: {name: lsn, age: 20} |
数组、list、set
用-值表示数组中的一个元素
多行写法:
1 | pets: |
行内写法:
1 | pets: [dog, pig, cat] |
对象数组、对象list、对象set
1 | students: |
占位符赋值
可以使用${key: defaultValue}的方式来赋值,若key不存在,则会使用defaultValue来赋值
1 | server: |
1 | server: |
SpringBoot读取YML
@Value注解
使用此注解只能获取简单类型(8大基本数据类型及其包装类型,String,Date)
1 | student: |
1 | package cn.xiaohupao.controller; |
注意:加了@Value的类必须是交由Spring容器管理的。
@ConfigurationProperties
1 | student: |
在类上添加注解@Component和@ConfigurationProperties(prefix=“配置前缀”)
1 | package cn.xiaohupao.pojo; |
注意,成员变量一定要提供setget方法
1 | package cn.xiaohupao.controller; |
YML练习
1 | student: |
1 | package cn.xiaohupao.pojo; |
1 | package cn.xiaohupao.pojo; |
1 | package cn.xiaohupao.controller; |
YML和properties配置的相互转换
转换网站:yaml转properties-properties转yaml
配置提示问题
如果使用@ConfigurationProperties注解,可以增加以下依赖,让我们在书写配置时有相应的提示
1 | <dependency> |
SpringBoot-常见场景
热部署
Spring-Boot为我们提供了一个方便我们开发测试的工具dev-tools。使用后可以实现热部署的效果。当我们运行了程序后对程序进行了修改,程序会自动重启
原理是使用了两个ClassLoder,一个ClassLoader加载哪些不会改变的类,另一个ClassLoader加载会更改的类,称之为Restart ClassLoader,这样在有代码更改的时候,原来的Restart ClassLoader被丢弃,重新创建一个Restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间
准备工作
设置IDEA自动编译:compiler -> Build project automatically
允许程序运行时自动启动:ctrl + alt+ shift+ / 选择Registry 找到compiler.automake.allow.when.app.running打勾
使用
添加依赖
1 | <dependency> |
触发热部署:
在修改完代码或静态资源时,可以切换到其他软件,让IDEA自动进行编译,自动编译后就会触发热部署。或者使用ctrl + F9触发重新编译
单元测试
可以使用SpringBoot整合Junit进行单元测试
使用
添加依赖
1 | <dependency> |
编写测试类
1 | package cn.xiaohupao; |
Junit常见问题
@SpringBootTest(classes = HelloApplication.class)可以用来指定启动类
兼容老版本
整合Mybatis
1 | CREATE TABLE `user` ( |
1 | package cn.xiaohupao.pojo; |
整合步骤
依赖
1 | <!--mybatis启动器--> |
配置数据库信息
1 | # SPRINGBOOT整合MYBATIS 相关配置 |
配置mybatis相关配置
1 | # 配置MYBATIS相关配置 |
编写Mapper接口
注意加上@Mapper和@Repository注解
1 | package cn.xiaohupao.mapper; |
编写mapper接口对应的xml文件
1 |
|
测试
1 | package cn.xiaohupao; |
Web开发
静态资源访问
可以将静态资源放到resources/static或resources/public或者resources/resources或者resources/META-INF/resources中即可。
例如需要访问:resources/static/index.html只需要在访问资源路径上写成/index.html即可
例如需要访问:resources/static/pages/login.html访问的资源路径写成:/pages/login.html
修改静态资源访问路径
SpringBoot默认的资源路径匹配为/**。如果想要修改可以通过spring.mvc.static-path-pattern这个配置进行修改。
例如想让访问静态资源url必须前缀有/res。例如/res/index.html才能访问到static目录中。我们可以修改如下:在application.yml
1 | spring: |
修改静态资源存放目录
1 | web: |
设置请求映射规则@RequestMapping
path或value属性都可以用来指定请求路径
例如:我们期望让请求的资源路径为/test/testPath的请求能够被testPath方法处理则可以写如下代码
1 | package cn.xiaohupao.controller; |
我们可以将注解加在方法上也可以加在类上
指定请求方式
1 |
- @PostMapping
- @GetMapping
- @PutMapping
- @DeleteMapping
指定请求参数
可以使用params属性来对请求参数进行一些限制。可以要求必须具有某些参数,或者是某些参数必须是某个值,或者某些参数必须不是某个值。
例如:期望资源的请求路径为/test/testParams的GET请求,并且请求参数中具有code参数的请求能够被testParams方法处理:
1 | package cn.xiaohupao.controller; |
指定请求头
可以使用headers属性来对请求头进行一些限制。
例如:期望请求资源路径为/test/testHeaders的GET请求,并且请求头中具有deviceType的请求能够被testHeaders方法处理:
1 | package cn.xiaohupao.controller; |
指定请求头Content-Type
可以使用consumes属性来对Content-Type这个请求头进行一些限制。
例如:期望让请求资源路径为/test/testConsumes的POST请求,并且请求头中的Content-Type头必须为multipart/from-data的请求能够被testConsumes方法处理:
获取请求参数
RestFul风格的接口一些参数是在请求路径上的。例如:/user/1这里1就是id
若想获取这种风格的数据可以使用@PathVariable来实现。
例如:要求定义一个RestFul风格的接口,该接口可以用来根据id查询用户。请求路径为/user,请求方式为GET
1 | package cn.xiaohupao.controller; |
例如:根据id和username查询用户。请求路径为/user,请求方式为Get,而请求参数id和name要写在请求路径上,例如/user/1/lsn:
1 | package cn.xiaohupao.controller; |
获取请求体中的Json格式参数
RestFul风格接口一些比较复杂的参数会转换成json通过请求体传递过来,这时候我们可以使用@RequestBody注解获取请求体中的数据。
Spring-boot的web启动器已经默认导入了jackson依赖,不需要格外导入。
使用
例如:定义一个RestFul风格接口,该接口可以新建用户。请求路径为/user,请求方式为POST。用户数据会转成json通过请求体传递
1 | { |
1 | package cn.xiaohupao.controller; |
获取参数封装成Map集合
1 | package cn.xiaohupao.controller; |
如果需要使用@RequestBody来获取请求体中的json并且进行转换,要求请求头Content-Type的值要为:application/json
获取QueryString格式参数
例如:要求定义一个接口,该接口的请求路径为/testRequestParam,请求方式无要求。参数为id和likes使用QueryString的格式传递。
参数单独的获取
如果我们把id、name、likes单独获取出来可以使用如下写法:
1 | package cn.xiaohupao.controller; |
可以使用@RequestParam注解解决方法参数名和请求参数名不一致的问题。
获取参数封装成实体对象
1 | package cn.xiaohupao.controller; |
相关注解其他属性
required
代表是否必须,默认值为true也就是必须要有对应的参数,如果没有就会报错。如果对应的参数可传可不传则可以把其设置为false。
defaultValue
如果对应参数没有,我们可以用defaultValue属性设置默认值
响应体相应数据
无论是RestFul风格还是我们之前web接触的异步请求,都需要把json放入响应体中
数据放到响应体
我们的SpringMVC为我们提供了@ResponseBody将把json放到响应体中
@ResponseBody可以加在类上和方法上
数据转换成Json
SpringMVC可以帮我们进行json的转换,不过需要进行相应配置
使用
只要把转换的数据直接作为方法的返回值返回即可。SpringMVC会帮我们把返回值转换成JSON。
例如:要求定义一个RestFul风格的接口,该接口可以用来根据ID查询用户,请求路径为/response/user,请求方式为GET。请求参数id要求写在请求路径上,例如/response/user/1这里i就是id。要求获取参数id,去查询对应id的用户信息。
1 | package cn.xiaohupao.controller; |
查询用户接口
1 | package cn.xiaohupao.mapper; |
1 |
|
1 | package cn.xiaohupao.service; |
1 | package cn.xiaohupao.service.impl; |
1 | package cn.xiaohupao.controller; |
1 | http://localhost:8080/user/findAll |
1 | [ |
接口响应格式统一
1 | package cn.xiaohupao.pojo; |
1 | package cn.xiaohupao.controller; |
1 | http://localhost:8080/user/findAll |
跨域请求
什么是跨域请求
浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的HTTP请求,默认情况下是被禁止的。 同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。
CORS解决跨域
CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing),允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
它通过服务器增加一个特殊的Header[Access-Control-Allow-Origin]来告诉客户端跨域的限制,如果浏览器支持CORS、并且判断Origin通过的话,就会允许XMLHttpRequest发起跨域请求。
SpringBoot使用CORS解决跨域
①使用@CrossOrigin
可以在支持跨域的方法上或者是Controller上加上@CrossOrigin注解
1 | package cn.xiaohupao.controller; |
使用WebMvcConfigurer的addCorsMappings方法配置CorsInterceptor
1 |
|
登录校验流程介绍
在前后端分离的场景中,很多时候会采用token的方案进行登录校验。
登录成功时,后端会根据一些用户信息生成一个token字符串返回给前端。
前端会存储这个token。以后前端发起请求时如果有token就会把token放在请求头中发送给后端。
后端接口就可以获取请求头中的token信息进行解析,如果解析不成功说明token超时了或者不是正确的token,相当于是未登录状态。
如果解析成功,说明前端是已经登录过的。
Token生成方案-JWT
引入依赖
1 | <dependency> |
然后可以使用下面的工具类来生成和解析token
1 | import io.jsonwebtoken.Claims; |
1 | public static void main(String[] args) throws Exception { |
登录接口
Controller
1 | package cn.xiaohupao.controller; |
Service
1 | package cn.xiaohupao.service; |
1 | package cn.xiaohupao.service.impl; |
Dao
1 | package cn.xiaohupao.mapper; |
1 |
|
Test
1 | http://localhost:80/sys_user/login |
1 | { |
1 | { |
拦截器
应用场景
如果我们想在多个Handler方法执行之前或者之后都进行一些处理,甚至某些情况下需要拦截掉,不让Handler方法执行。那么可以使用SpringMVC提供的拦截器。
拦截器和过滤器的区别
过滤器是在Servlet执行之前或者之后进行处理。而拦截器是对Handler执行前后进行处理
创建拦截器并配置拦截器
①创建类实现HandlerInterceptor接口
1 | package cn.xiaohupao.interceptor; |
配置拦截器
1 | package cn.xiaohupao.config; |
异常统一处理
②@ControllerAdvice
创建类加上@ControllerAdvice注解进行标识
1 | package cn.xiaohupao.exception; |
1 | package cn.xiaohupao.exception; |
获取web原生对象
我们经常要使用到request对象,response,session对象等。我们也可以通过SpringMVC获取到这些对象。我们只需要在方法上添加对应类型的参数类型即可,SpringMVC会把我们需要的对象传给我们的形参。
1 |
|
自定义参数解析
1 | package cn.xiaohupao.controller; |
如果想要实现像获取请求体中的数据那样,在Handler方法的参数上增加一个@ResponseBody注解就可以获取到对应的数据的话。可以使用HandlerMethodArgumentResolver来实现自定义的参数解析。
1 | package cn.xiaohupao.resolver; |
1 | package cn.xiaohupao.resolver; |
1 | package cn.xiaohupao.config; |