依赖管理机制
- 导入场景启动器后,会根据maven依赖传递的原理,将这个场景下所有的核心依赖都导入进来
- 每个boot项目都有一个父项目spring-boot-starter-parent,parent的父项目是spring-boot-dependencies,spring-boot-dependencies其中有着依赖管理,所以在boot项目的maven下可以不需要指定依赖的版本
- 如果要自定义版本号,可以直接在当前项目properties标签中声明父项目用的版本属性的key或dependency中直接指定版本。(利用maven的就近原则,会优先找当前项目中的版本,再找父项目中的版本)
- boot父项目没有管理的依赖需要自行声明版本
自动配置机制
- 导入相应场景后,ioc容器会自动配置好这个场景的核心组件
- springboot会自动配置包扫描,默认只会扫描主程序所在的包及其子包,@SpringBootApplication注解标注的类就是主程序,扫描的包中的所有组件会配置到ioc容器中
- 如果要指定主程序外的包进行包扫描,可以使用@SpringBootApplication注解的scanBasePackages属性指定要扫描的包的路径。
- 配置文件中的所有配置项是和某个类的对象值进行一一绑定的,绑定了配置文件中的每一项默认值的类称为配置属性类
- 导入场景spring-boot-starter-web后,场景启动器除了会导入相关功能依赖,还会导入一个spring-boot-starter。spring-boot-starter是其他starter的starter,是基础核心starter。
- spring-boot-starter导入了一个包spring-boot-autoconfigure。包里有着各种场景的AutoConfiguration自动配置类。虽然全场景的自动配置都在spring-boot-autoconfigure包中,但不是会全部开启,项目导入了哪个场景就开启哪个配置
- 总结即:导入场景启动器、触发
spring-boot-autoconfigure
这个包的自动配置生效、容器中就会具有相关场景的功能
常用注解
SpringBoot摒弃了xml配置方式,改为全注解驱动。
组件的注册注解
组件的配置注解与springframework的配置一致,见spring-ioc的学习
补充:
- @SpringBootConfiguration注解继承于@Configuration注解,作用和@Configuration注解的作用一致
- @Import注解的额外使用,除了能用来导入其他配置类的信息,还有一个用法。在配置类上加上@Import注解,在其中指定类的class实例,就可以在ioc容器中导入相应的类的组件,可以用来导入第三方的组件。
条件注解
如果注解指定的条件成立,则触发指定行为。
条件的注解的格式为@ConditionalOnXxxx......
@ConditionalOnClass
如果类路径中存在这个类,则触发指定行为
@ConditionalOnMissingClass
如果类路径中不存在这个类,则触发指定行为
@ConditionalOnBean
如果容器中存在这个组件,则触发指定行为
@ConditionalOnMissingBean
如果容器中不存在这个组件,则触发指定行为
条件注解使用场景:例:若容器中有A类的组件,则将B类的组件加入到IoC容器。只要在配置B类的操作上,加上一个@ConditionalOnBean(A.class)即可,也可以在@ConditionalOnBean注解的name属性中指定要判断的组件的类的全限定符
java
@SpringBootConfiguration
public class SpringBootConfig {
@ConditionalOnBean(A.class)
@Bean
public B b(){
return new B();
}
}
其他的条件注解使用方法大致相同,当然,条件注解也可以放在配置类上方,代表只有满足条件,此配置类才会生效
属性绑定注解
除了在@Bean注解的方法中指定组件的属性值,还可以使用@ConfigurationProperties注解声明组件和配置文件的哪些配置项进行绑定
@ConfigurationProperties注解的使用:
在@ConfigurationProperties注解的prefix属性中指定前缀,此注解会将此前缀加在类的属性名前,再与application.properties配置文件中的配置属性对应名称进行值绑定
前提是,属性绑定的是类的组件,该类要放在ioc容器中
例:
application.properties:
properties
pig.id=1
pig.name=Tom
pig.age=8
Pig类:
java
@ConfigurationProperties(prefix = "pig")
@Component
public class Pig {
private Integer id;
private String name;
private Integer age;
}
Pig在ioc中的组件的id、name、age属性值就为分别1、Tom、8
@ConfigurationProperties注解可以放在类上,也可以放在方法上(即可以放在@Bean注解的方法上)
@EnableConfigurationProperties
此注解在配置类上使用
@EnableConfigurationProperties的作用:
- 在@EnableConfigurationProperties注解的value属性中指定类的class实例,会自动开启指定类组件的属性绑定,但是属性绑定的前缀还是要使用@ConfigurationProperties注解
- 默认会把value属性中指定的类的组件放在ioc容器中
通常此注解用来配置第三方的类的组件注册和组件的属性绑定
自动配置原理
流程:
导入starter-web:导入web开发场景
- 场景启动器导入了相关场景的所有依赖
- 每个场景启动器都引入了一个spring-boot-starter,场景核心启动器
- 核心场景启动器引入了spring-boot-autoconfigure包
- spring-boot-autoconfigure里面囊括了所有场景的所有配置
- 只要这个包下的所有类都能生效,那么相当于SpringBoot官方写好的整合功能就生效了
- SptingBoot默认扫描不到spring-boot-autoconfigure下写好的所有配置类(这些配置类写好了整合操作),默认只扫描主程序所在的包
主程序:@SpringBootApplication
SpringBootApplication由三个注解组成:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
SpringBoot默认只能扫描自己主程序所在的包,扫描不到spring-boot-configure包中官方写好的配置类
@EnableAutoConfiguration:SpringBoot开启自动配置的核心
- 是由
@Import(AutoConfigurationImportSelector.class)
提供功能:批量给容器中导入组件。
- SpringBoot启动会默认加载 142个配置类。
- 这142个配置类来自于
spring-boot-autoconfigure
下META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration**.imports
文件指定的- 项目启动的时候利用 @Import 批量导入组件机制把
autoconfigure
包下的142xxxxAutoConfiguration
类导入进来(自动配置类)- 虽然导入了
142
个自动配置类,但是默认都不生效按需生效:
- 每一个自动配置类,都有条件注解@ConditionalOnXxx只有条件成立才能生效
- 条件注解生效后,就会使用加@Bean的方式给容器中放入一系列组件
- 每个自动配置类 都可能有这个注解
@EnableConfigurationProperties(xxxProperties.class)
,用来把配置文件中配的指定前缀的属性值封装到xxxProperties
属性类中- 给容器 中放的所有组件 的一些核心参数 ,都来自于
xxxProperties
。xxxProperties
都是和配置文件绑定。- 所以,只需要改配置文件的值,核心组件的底层参数都能修改
写业务,全程无需关心各种整合(底层已经写好了整合,并且生效)
核心流程总结:
1、导入
starter
,就会导入autoconfigure
包。2、
autoconfigure
包里面 有一个文件META-INF/spring/**org.springframework.boot.autoconfigure.AutoConfiguration**.imports
,里面指定的所有启动要加载的自动配置类3、@EnableAutoConfiguration 会自动的把上面文件里面写的所有自动配置类都导入进来。xxxAutoConfiguration 是有条件注解进行按需加载
4、
xxxAutoConfiguration
给容器中导入一堆组件,组件都是从xxxProperties
中提取属性值5、
xxxProperties
又是和配置文件进行了绑定
YAML配置文件
若使用application.properties配置文件进行集中化配置,当配置多的时候,难以阅读和修改,层次结构辨识度不高。
yaml配置文件层次分明,更方便阅读和改写
基本语法:
- 大小写敏感
- 使用缩进表示层级关系,k: v,使用空格分割k,v
- 缩进时不允许使用Tab键,只允许使用空格。换行
- 缩进的空格数目不重要,只要相同层级 的元素左侧对齐即可(通常为两个空格)
- # 表示注释,从这个字符一直到行尾,都会被解析器忽略。
例如:
yaml
#配置
server:
port: 8080
servlet:
context-path: /
#连接池配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
url: jdbc:mysql:///database
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
# mybatis-plus的配置
mybatis-plus:
type-aliases-package: com.atguigu.pojo
global-config:
db-config:
logic-delete-field: isDeleted#全局逻辑删除
id-type:auto#主键策略自增长
table-prefix: news_#设置表的前缀
# jwt的配置
#jwt配置
jwt:
token:
tokenExpiration: 120#有效时间,单位为分钟
tokenSignKey: headline123456#当前程序签名秘钥 自定义
yaml
#表示对象
person:
name: 张三
age: 18
birthDay: 2010/10/10 12:12:12
like: true
child:
name: 李四
age: 20
birthDay: 2018/10/10
text: ["abc","def"] #集合或数组的第一种写法
dogs:
- name: 小黑 # 第二种写法,表示集合中的元素,每个元素前加一个- (横杠加空格)
age: 3
- name: 小白
age: 2
cats:
c1:
name: 小蓝
age: 3
c2: {name: 小绿,age: 2} #对象也可用{}表示
而在properties中表示对象:
properties
person.name=张三
person.age=18
person.birthDay=2010/10/12 12:12:12
person.like=true
person.child.name=李四
person.child.age=12
person.child.birthDay=2018/10/12
person.child.text[0]=abc
person.child.text[1]=def
person.dogs[0].name=小黑
person.dogs[0].age=3
person.dogs[1].name=小白
person.dogs[1].age=2
person.cats.c1.name=小蓝
person.cats.c1.age=3
person.cats.c2.name=小灰
person.cats.c2.age=2
可以看出yaml文件更为层次清晰,易于阅读
注:
- 驼峰式的写法建议写为横杠式的写法,绑定时会自动映射,比如属性名未birthDay,建议在yaml文件中写作birth-day
- 单引号引用的字符串不会转义其中的特殊字符,比如/n在单引号中就是普通的/n字符串,而双引号中的特殊字符会转义比如/n在双引号中表示换行符
|
开头,大文本写在下层,保留文本格式,换行符正确显示,类似于模板字符串>
开头,大文本写在下层,折叠换行符,即将换行符变成空格显示- 多文档合并:使用
---
可以把多个yaml文档合并在一个文档中,每个文档区依然认为内容独立
日志配置
SpringBoot默认日志配置是SLF4j下的Logback,也支持jul和Log4j2
SpringBoot日志配置流程:
- 每个starter场景,都会导入一个核心场景spring-boot-starter
- 核心场景引入了日志的所有功能spring-boot-starter-logging
- 默认使用logback+slf4j组合作为默认底层日志
- 日志是系统一启动就要用的,xxxAutoConfiguration是系统启动后放好的组件
- 日志是利用监听器机制配置好的(ApplicationListener)
- 日志所有的配置都可以通过修改配置文件实现。(以logging开始的所有配置)
日志格式
默认输出格式:
- 时间和日期:毫秒级精度
- 日志级别:ERROR, WARN, INFO, DEBUG, or TRACE.
- 进程 ID
- ---: 消息分割符
- 线程名: 使用[]包含
- Logger 名: 通常是产生日志的类名
- 消息: 日志记录的内容
arduino
2024-03-13T21:28:46.239+08:00 INFO 560 --- [boot3-02-plus-demo] [ main] c.ergou.boot.Boot302PlusDemoApplication : Started Boot302PlusDemoApplication in 0.855 seconds (process running for 1.178)
记录日志
可以创建一个Logger类的对象,在调用此对象的info方法,传入要输出到日志的字符串
java
Logger logger = LoggerFactory.getLogger(getClass());
或者使用Lombok的@Slf4j注解,在类上使用@Slf4j注解,直接调用log.info
("......")方法,也是传入要输出到日志的字符串
日志级别
-
由低到高:
ALL,TRACE, DEBUG, INFO, WARN, ERROR,FATAL,OFF
; -
只会打印指定级别及以上级别的日志
- ALL:打印所有日志
- TRACE:追踪框架详细流程日志,一般不使用
- DEBUG:开发调试细节日志
- INFO:关键、感兴趣信息日志
- WARN:警告但不是错误的信息日志,比如:版本过时
- ERROR:业务错误日志,比如出现各种异常
- FATAL:致命错误日志,比如jvm系统崩溃
- OFF:关闭所有日志记录
- 不指定级别的所有类,都使用root指定的级别作为默认级别
-
SpringBoot日志默认级别是 INFO
- 在application.properties/yaml中配置logging.level.=指定日志级别
- level可取值范围:
TRACE, DEBUG, INFO, WARN, ERROR, FATAL, or OFF
,定义在LogLevel
类中- root 的logger-name叫root,可以配置logging.level.root=warn,代表所有未指定日志级别都使用 root 的 warn 级别
- 可以在logging.level.后指定包的全限定符,指定该包下的日志级别(也可以写类的全限定符,让日志级别精确到类)
日志分组
在配置文件中,以logging.group. 为前缀,在=后面写上该组的组员的全限定符,组员的全限定符之间用逗号隔开
再用logging.level.组名=日志级别,就可以指定该组的日志级别
properties
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
logging.level.tomcat=trace
SpringBoot 预定义两个组
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.name加上配置logging.gile.path,指定了日志文件的路径和文件名,则会在指定路径下生成一个指定文件名的文件(以 路径.文件名 作为logging.file.name的配置也是一样的效果)
logging.file.name | logging.file.path | 示例 | 效果 |
---|---|---|---|
未指定 | 未指定 | 仅控制台输出 | |
指定 | 未指定 | my.log | 写入指定文件。可以加路径 |
未指定 | 指定 | /var/log | 写入指定目录,文件名为spring.log |
指定 | 指定 | 以logging.file.name为准 |
归档与切割
归档:将日志按时间段分开存储,比如每天的日志单独存到一个文档中
切割:每个文件指定存储空间,超过此指定的存储空间则切割为另外一个文件
配置项 | 描述 |
---|---|
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). |
自定义日志系统
通常我们配置 application.properties 就够了。当然也可以自定义。比如:
日志系统 | 自定义时该使用的文件名 |
---|---|
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 |
切换日志组合
要切换日志组合,步骤(在maven文件中):
- 先排除SpringBoot的默认日志配置,让其不生效(使用你exclusions标签)
- 再引入要使用的日志依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>