SpringBoot3学习笔记
该笔记基于b站视频SpringBoot零基础教程学习完成
1. 快速入门
1.1 简介
环境要求
| 环境&工具 | 版本(or later) |
|---|---|
| SpringBoot | 3.0.5+ |
| IDEA | 2021.2.1+ |
| Java | 17+ |
| Maven | 3.5+ |
| Tomcat | 10.0+ |
| Servlet | 5.0+ |
| GraalVM Community | 22.3+ |
| Native Build Tools | 0.9.19+ |
SpringBoot是什么
SpringBoot 帮我们简单、快速地创建一个独立的、生产级别的 Spring 应用(说明:SpringBoot底层是Spring)大多数 SpringBoot 应用只需要编写少量配置即可快速整合 Spring 平台以及第三方技术
特性:简化开发,简化配置,简化整合,简化部署,简化监控,简化运维
1.2 开发流程
创建项目
1 | |
导入场景
1 | |
主程序
1 | |
业务
1 | |
测试
启动项目,默认端口号8080

打包
引入打包插件
1 | |
mvn-clean package 把项目打成可自行的jar包,打包后可以在target中找到

java -jar demo.jar 启动项目
1.3 Spring Initializr
通过Spring Initializr 来创建springboot项目
选择需要的依赖

2. 应用分析
2.1 依赖管理机制
为什么导入starter-web所有相关的依赖都导入进来了?
- 想要开发什么场景、就导入对应的场景启动器(依赖)
- maven依赖传递原则,A依赖了B,B又依赖于C,所以A依赖于B和C。所以导入了场景启动器后,在场景启动器中会将所有需要的依赖都导入进来
为什么版本号都不用写
- 每个boot项目都会有一个父项目
spring-boot-starter-parent - parent的父项目是
spring-boot-dependencies - 父项目 版本仲裁中心,把常见的jar的依赖版本都声明号了
自定义版本号
- 利用maven的就近原则,在导入依赖时手动声明版本,则该依赖的版本会替换父项目默认的版本
- 在项目pom文件中的
properties属性中加入版本管理
第三方的jar包
- boot父项目没有进行版本管理的要自定义版本号
2.2 自动配置机制
初步理解
- 自动配置
Tomcat、SpringMVC等- 导入什么场景,容器中就会自动配置好这个场景的核心组件
- 容器中有了什么组件就会有什么功能
- 默认的包扫描规则
@SprongBootApplication标注的类就是主程序类- SpringBoot只会扫描主程序所在的包及其下面的包
- 自定义扫描路径
@SpringBootApplication(scanBasePackages = "com.zheng"),在启动类的@SpringBootApplication注解上添加属性scanBasePackages,属性的值是需要扫描的包@ComponentScan("com.zheng"),在启动类中添加注解@ComponentScan,属性值是需要扫描的包
- 配置默认值
- 配置文件的所有配置项是和某个类的对象值进行一一绑定的
- 绑定了配置文件中每一项值的类:属性类
- 例如:
ServerProperties绑定了所有Tomcat服务器有关的配置、MultipartProperties绑定了所有文件上传相关的配置
- 按需加载自动配置
- 导入场景
spring-boot-starter-web - 场景启动器除了会导入相关的依赖,还会导入一个
spring-boot-starter,它是所有starter的starter,是基础的starter spring-boot-starter导入了一个包spring-boot-autoconfigure,这个包里面包含各种场景的AutoConfiguration自动配置类- 虽然全场景的自动配置都在
spring-boot-autoconfigure这个包,但是不是全部都开启的,只有需要的才会开启
- 导入场景
总结:导入场景启动器、触发Spring-boot-autoconfigure这个包的自动配置生效、容器中就会具有相关场景的功能
3. 核心技能
3.1 常见注解
组件注解
@Configuration、@SpringBootConfiguration
@Bean、@Scope
@Controller、@Service、@Repository、@Component
@Import
@ComponentScan
配置类:
- @Configuration编写一个配置类
- 在配置类中,自定义方法给容器中注册组件。配合@Bean
- 使用@Import导入第三方的组件
条件注解
如果注解指定的条件成立,则触发指定行为
- @ConditionalOnClass:如果类路径中存在这个类,则触发指定行为
- @ConditionalOnMissingClass:如果类路径中不存在这个类,则触发指定行为
- @ConditionalOnBean:如果容器中存在这个Bean(组件),则触发指定行为
- @ConditionalOnMissingBean:如果容器中不存在这个Bean(组件),则触发指定行为
- @ConditionalOnBean(value=组件类型,name=组件名字):判断容器中是否有这个类型的组件,并且名字是指定的值
属性绑定
@ConfigurationProperties
将容器中任意组件(Bean)的属性值和配置文件的配置项的值进行绑定
- 给容器中注册组件(@Component、@Bean)
- 使用@ConfigurationProperties声明组件和配置文件的哪些配置进行绑定
@EnableConfigurationProperties
- Springboot默认是不会扫描第三方包,如果导入了第三方的包,即时组件上标注了@ConfigurationProperties注解也没用,因为组件扫描不进来,这时候就需要@EnableConfigurationProperties注解来进行属性的绑定并把组件注册进容器
3.2 YAML配置文件
基本语法
- 大小写敏感
- 使用缩进表示层级关系,k: v,使用空格分割k,v
- 缩进的空格数随意,主要相同层级的元素左对齐即可
#表示注解,从这个字符一直到行尾,都会被解析器忽略
示例
第一4个类

只有Person类需要注入到组件中去
1 | |
获取person并输出
1 | |
properties表示法
1 | |
输出结果

yaml表示法
1 | |
输出结果,要把application.properties中的数据注释掉在运行,否则会输出application.properties中的数据,因为properties的优先级大于yaml

细节
- birthDay推荐写为brith-day
- 文本:
- 单引号不会转义[会把\n作为普通字符输出]
- 双引号会转义[\n会显示为换行符]
- 多文档合并
- 使用
---可以把多个yaml文档合并在一个文档中,每个文档区依然认为内容独立
- 使用
lombok
使用lombok创建可以简化JavaBean的开发。能自动生成setter、getter、构造器、toString方法、自动生成Builder模式等
@Data默认只会生成无参构造器,如果需要有参构造器需要用注解自己添加
``@NoArgsConstructor` 自动生成无参构造器
@AllArgsConstructor 自动生成全参构造器
1 | |
3.3 日志配置
项目开发不要编写System.out.println(),应该使用日志记录信息
简介
- Spirng使用
commons-logging作为内部日志,但底层日志实现是开放的,可以对接其它日志框架,从Spring5开始把commons-logging集成在spring中,不需要再引入 - 支持
jul,log4j2,logback。SpringBoot提供了默认的控制台输出配置,也可以配置输出为文件 logback是默认使用的
SpringBoot是如何把日志默认配置好的
- 每个
starter场景都会导入一个核心场景spring-boot-starter - 核心场景引用了日志的所有功能
spring-boot-starter-logging - 默认使用了
logback + slf4j作为默认底层日志 - 日志是系统一启动就要用的
- 日志是利用监听器机制配置好的,
ApplicationListener - 日志所有的配置都是可以通过修改配置文件实现的。以
logging开始所有的配置
日志格式
1 | |
默认输出格式:
- 时间和容器:毫秒级精准 2023-11-17T15:57:49.570+08:00
- 日志级别:
ERROR,WARN,INFO,DEBUG,TRACEINFO - 进程ID 17668
- 消息分隔符 —
- 线程名:使用[]包含 [ main]
- Logger名:通常是产生日志的类名 o.apache.catalina.core.StandardService
- 消息:日志记录的内容 Starting service [Tomcat]
注意:logback没有FATAL级别,对应的是ERROR
日志的格式是可以修改的,通过在配置文件中自定义日志格式
logging.pattern.console 修改控制台日志的格式
logging.pattern.file 修改日志文件中日志的格式
logging.pattern.dateformat 修改日期格式
记录日志
在类上加入注解@Slf4j后,可以通过log.info()在控制台打印日志
1 | |
1 | |
日志级别
由低到高:
ALL,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF- 只会打印指定级别及以上级别的日志
- ALL:打印所有日志
- TRACE:追踪框架详细流程日志,一般不使用
- DEBUG:开发调试细节日志
- INFO:关键、感兴趣的信息日志,一般通过手动INFO在控制台输出自己需要的提示信息
- WARN:警告但不是错误的信息日志,比如版本过低警告
- ERROR:业务错误日志,比如出现各种异常
- FATAL:致命错误日志,比如JVM系统崩溃
- OFF:关闭所有日志
所有类的默认日志级别都使用root指定的级别作为默认级别
SpringBoot的日志默认级别是
INFO可以修改所有类的日志级别和指定一个类的日志级别,通过配置
application.properties/yaml文件1
2logging.level.root=info
logging.level.com.zheng.logging.controller.HelloController=debug- logging.level.root=info 设置所有类的日志级别为INFO
- logging.level.com.zheng.logging.controller.HelloController=debug 设置com.zheng.logging.controller.HelloController这个类的日志级别为DEBUG
日志分组
将相关的logger分组在一起,统一配置。SpringBoot也支持。比如把Tomcat相关的日志统一设置
1 | |
SpringBoot预定义了两个分组web和sql
| Name | Loggers |
|---|---|
| web | org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans |
| sql | org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener |
文件输出
SpringBoot默认只把日志写在控制台,如果想额外记录日志到文件,可以在application,properties中添加logging.file.name或者logging.file.path配置项
| logging.file.name | logging.file.path | 示例 | 效果 |
|---|---|---|---|
| 未指定 | 未指定 | 仅控制台输出 | |
| 指定 | 未指定 | my.log | 写入指定文件。可以加路径 |
| 未指定 | 指定 | /var/log | 写入指定目录,文件名为spring.log |
| 指定 | 指定 | 以logging.file.name为准 |
当两个配置项都存在时以logging.file.name为准
文件归档与滚动切割
归档:每天的日志单独存放在一个文件中
切割:指定每个文件的存储上限,超过上限时切割成另一个文件
每天的日志应该单独分割出来存储。如果使用
logback(SpringBoot默认整合),可以通过application.properties/yaml文件指定日志滚动规则如果是其他日志系统,需要自行配置,添加log4j2.xml或log4j2-spring.xml
支持的滚动规则如下
配置项 描述 logging.logback.rollingpolicy.file-name-pattern 日志存档的文件名格式(默认值:${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz) logging.logback.rollingpolicy.clean-history-on-start 应用启动时是否清除以前存档(默认值:false) logging.logback.rollingpolicy.max-file-size 存档前,每个日志文件的最大大小(默认值:10MB) logging.logback.rollingpolicy.total-size-cap 日志文件被删除之前,可以容纳的最大大小(默认值:0B)。设置1GB则磁盘存储超过 1GB 日志后就会删除旧日志文件 logging.logback.rollingpolicy.max-history 日志文件保存的最大天数(默认值:7).
自定义日志系统
| 日志系统 | 自定义 |
|---|---|
| Logback | logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy |
| Log4j2 | log4j2-spring.xml or log4j2.xml |
| JDK (Java Util Logging) | logging.properties |
建议在日志配置中使用-spring变量,例如配置文件名用logback-spring.xml而不是logback.xml。如果不添加-spring,spring无法完全控制日志初始化
4. Web开发
4.1 Web场景
整合文web场景
1 | |
引入了autoconfigure功能@EnableAutoConfiguration注解使用@Import(AutoConfigurationImportSelector.calss)批量导入组件
绑定了配置文件的一堆配置项
- SpringMVC的所有配置
spring.mvc - Web场景通用配置
spring.web - 文件上传配置
spring.servlet.multipart - 服务器的配置
server
5. 数据访问
5.1 SpringBoot整合Spring、MyBatis、SpringMVC
详情见:SpringBoot整合SSM
所有的Mybatis配置写在application.properties中
所有的sql写在对应xml文件中或者通过注解写在对应的mapper接口上
5.2 自动配置分析
jdbc场景的自动配置
mybatis-spring-boot-starter导入spring-boot-starter-jdbc,jdbc是操作数据库的场景- jdbc场景的几个自动装配
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- 数据源的自动装配
- 所有和数据源有关的配置绑定在
DataSourceProperties中 - 默认使用
HikariDataSource
- org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
- 给容器中放了
JdbcTemplate操作数据库
- 给容器中放了
- org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
- 支持事务管理
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
MyBatisAutoConfiguration配置了MyBatis的整合流程
mybatis-spring-boot-starter导入了mybatis-spring-boot-autoconfigure- 默认加载两个自动配置类
- org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration
- org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
- 必须在数据源配置好后才会配置
- 给容器中
SqlSessionFactory组件创建和数据库的一次会话 - 给容器中
SqlSessionTemplate操作数据库
- MyBatis的所有配置都绑定在
MybatisProperties中
6. 基础特性
6.1. SpringApplication
自定义banner
- 类路径添加banner.txt或者设置spring.banner.location就可以定制banner了
- spring.banner.location的默认值是classpath:banner.txt(类路径添加banner.txt)
- 自定义banner推荐网站:Spring Boot自定义启动Banner在线生成工具
- 关闭banner,在application.properties中添加配置
spring.main.banner-mode=off
测试
1 | |
自定义 SpringApplication
1 | |
通过FluentBuilderAPI来自定义
1 | |
6.2 Profiles
Profiles是一种配置集合,开发人员可以根据不同的开发环境、需求或者配置条件来定制构建过程
标识环境
任何@Componet,@Configuration或@ConfigurationProperties可以使用@Profile标记,来指定何时被加载。容器中的组件都可以被@Profiles标记
激活环境
通过配置文件来配置激活指定环境
1 | |
也可用在启动项目时使用命令行激活:--spirng.profiles.active=dev
环境包含
激活指定的一个或多个环境:
spring.profiles.active=production指定默认环境:
spring.profiles.default=default包含指定环境,无论激活的是哪个环境,指定环境都会被激活生效:
spring.profiles.include=dev例如
1
2spring.profiles.include[0]=common
spring.profiles.include[1]=local
=后面的都是自定义的环境名
Profile分组
创建prod组,指定包含db和mq配置
1 | |
使用--spring.profiles.active=prod,就会激活prod,db,mp配置文件
Profile配置文件
application.properties:主配置文件,在任何环境下都会生效application-{profile}.properties/yaml:可以作为指定环境的配置文件,例如application-dev.propertiesapplication-test.yaml
- 激活这个环境,配置就会生效
- 配置的优先级:自定义环境的配置文件优先级大于主配置文件优先级,
profile优先级>application
6.3 外部化配置
线上应用如何快速修改配置,并应用最新配置?
- SpringBoot使用配置优先级 + 外部配置简化配置更新、简化运维
- 只需要在项目的jar包所在的文件夹下面在放一个
application.properties最新配置文件,重启项目就能更新最新配置
配置优先级
- 默认属性(通过
SpringApplication.setDefaultProperties指定的) - @PropertySource指定加载的配置(需要写在@Configuration类上才可生效)
- 配置文件(pplication.properties/yml等)
- RandomValuePropertySource支持的random.*配置(如:@Value(“${random.int}”))
- OS 环境变量
- Java 系统属性(System.getProperties())
- JNDI 属性(来自java:comp/env)
- ServletContext 初始化参数
- ServletConfig 初始化参数
- SPRING_APPLICATION_JSON属性(内置在环境变量或系统属性中的 JSON)
- 命令行参数
- 测试属性。(@SpringBootTest进行测试时指定的属性)
- 测试类@TestPropertySource注解
- Devtools 设置的全局属性。($HOME/.config/spring-boot)
配置文件的优先级如下(后面的覆盖前面的)
- jar包内的
application.properties.yml - jar包内的
application-{profile}.properties/yml - jar包外的
application.properties/yml - jar包外的
application-{profile}.properties/yml - 如果
properties和yml同时存在,properties优先
6.4 单元测试
SpringBoot提供一系列测试工具及注解方便我们进行测试
我们只需要导入spring-boot-starter-test即可整合测试
1 | |
spring-boot-starter-test默认提供了下面的库供我们测试使用
- JUnit 5
- Spring Test
- AssertJ
- Hamcrest
- Mockito
- JSONassert
- JsonPath
如果要测试组件,在测试类中通过@Autowired导入需要测试的组件即可
注解
JUnit 5 的注解相对于 JUnit 4 有所变化
- **@Test :**表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
- **@ParameterizedTest :**表示方法是参数化测试,下方会有详细介绍
- **@RepeatedTest :**表示方法可重复执行,下方会有详细介绍
- **@DisplayName :**为测试类或者测试方法设置展示名称
- **@BeforeEach :**表示在每个单元测试之前执行
- **@AfterEach :**表示在每个单元测试之后执行
- **@BeforeAll :**表示在所有单元测试之前执行
- **@AfterAll :**表示在所有单元测试之后执行
- **@Tag :**表示单元测试类别,类似于JUnit4中的@Categories
- **@Disabled :**表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
- **@Timeout :**表示测试方法运行如果超过了指定时间将会返回错误
- **@ExtendWith :**为测试类或测试方法提供扩展类引用
断言
| 方法 | 说明 |
|---|---|
| assertEquals | 判断两个对象或两个原始类型是否相等 |
| assertNotEquals | 判断两个对象或两个原始类型是否不相等 |
| assertSame | 判断两个对象引用是否指向同一个对象 |
| assertNotSame | 判断两个对象引用是否指向不同的对象 |
| assertTrue | 判断给定的布尔值是否为 true |
| assertFalse | 判断给定的布尔值是否为 false |
| assertNull | 判断给定的对象引用是否为 null |
| assertNotNull | 判断给定的对象引用是否不为 null |
| assertArrayEquals | 数组断言 |
| assertAll | 组合断言 |
| assertThrows | 异常断言 |
| assertTimeout | 超时断言 |
| fail | 快速失败 |
参数化测试
参数化测试是JUnit5很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。
利用**@ValueSource**等注解,指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。
- @ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
- @NullSource: 表示为参数化测试提供一个null的入参
- @EnumSource: 表示为参数化测试提供一个枚举入参
- @CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
- @MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)