**# SpringBoot
简介
SpringBoot 是一个简化 Spring 应用程序开发的框架,它提供了一系列的 starter
模块,用于集成各种常见的 Spring 框架组件。
提倡约定大于配置,提供了默认配置、自动化配置和嵌入式服务器等功能,使得开发人员能快速构建、测试和部署 Spring 应用。
SpringBoot 特点
简化配置:通过自动配置(EnableAutoConfiguration
),根据项目的 classPath
、application
配置文件等自动为应用添加相应的依赖和配置。 内置服务器:内置 Tomcat、Jetty、Netty(仅限 WebFlux)等服务器,程序可以直接通过 java -jar
方式启动 生态强大:集成 Spring 全家桶,而且各主流组件也提供第三方的 stater
模块来支持 SpringBoot
可以通过切换依赖来切换嵌入式 Web 容器,比如移除 Tomcat 依赖,添加 Jetty 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
// 引入 webflux 依赖就自动选择 Netty 作为 Web 容器了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
版本演进
SpringBoot 2.x 改进
- 基于 Spring 5.x ,引入了响应式编程(WebFlux)
- 升级了嵌入式 Web 容器的默认版本
- 基于 JDK8 + ,底层组件和框架本身做了大量性能优化,更适合云原生应用和大规模微服务架构
- 自动配置机制增强,使应用自动配置更加智能
SpringBoot 3.x 改进
- 从 Java EE 迁移到 Jakarta EE,一些核心包名从
javax.*
变更为jakarta.*
- 基于 JDK17+ ,充分利用 JDK17 的新特性进行了性能优化
- 提供了对
GraalVM
的开箱即用支持 - 安全性增强(
Spring Security 5
升级为Spring Security 6
) - 对内部依赖进行模块化调整,优化依赖管理,删除了一些不再使用或过时的库,更轻量化
GraalVM
SpringBoot 3.X 很重要的一项新特性就是原生支持GraalVM,它是什么、和传统 JVM 有什么区别呢?
我们先来回顾传统 JVM 的运行机制:.java
源文件先被编译为与平台无关的 .class
字节码,然后由 JVM 逐条解释字节码为机器码进行执行。 这个解释执行的过程非常灵活,支持诸如反射这类动态特性,但是没有经过编译优化性能较差。
为了解决这个运行时性能差的问题,JVM 引入了JIT(Just In Time
)实时编译技术,将热点函数编译为汇编代码(经过汇编器即可转换为操作系统直接执行的机器码)。 OpenJDK 使用的 JIT 编译器分为 C1 和 C2,前者编译优化较少,后者编译优化较多,但是性能相对更好但耗费系统资源也更多。
GraalVM 是指以 JVM 为基础,以 Graal 即时编译器为核心,以能运行多种语言为目标,包含一些里框架和技术的大杂烩,想成为一统天下的最终虚拟机。
- 可以作为传统 JVM 场景使用,其实就是原来 C2 编译器做的事情交给了 Graal 编译器来做,性能比 C2 更好
- 支持 Java 的 AOT(Ahead-of-Time),编译产物不再是 Java 字节码,而是可在目标系统上直接执行的机器码(不依赖运行时环境的可执行文件,如
.exe
)
在初次发现 GraalVM 可以将 Java 程序编译为可以直接执行的 .exe
程序时,我是很兴奋的,于是直接开始上手尝试:
- 下载 GraalVM 官方包:https://www.graalvm.org/downloads/ ,解压到本地,并配置环境变量,然后使用
java -version
和native-image
命令验证
- 安装
Visual Studio
组件 (Windows 系统下编译原生可执行文件需要)
- 创建 SpringBoot 项目,选择我们下载的
GraalVM JDK
,并配置native-image
支持插件
GraalVM 静态编译的致命痛点 -- 反射等动态特性
GraalVM 可以编译生成为原生可执行文件,解决了 Java 应该 JVM 冷启动问题,消耗资源更少、性能更快。
但是再厉害的静态编译优化也无法完全预测诸如反射等动态特性,SpingBoot 3.x 为此提供了大部分场景下的支持,但依然不能完全解决,部分场景需要开发者手动提供配置解决
启动流程
1. 启动 main() 方法
应用从 main()
方法启动,并通过 SpringApplication.run()
引导应用启动
2. 创建 SpringApplication 对象
首先会调用 SpringApplication
的构造方法,创建 SpringApplication
对象,并进行一些初始化工作,比如:
- 推断应用类型,到底是
Servlet
(传统 Web 应用) 还是Reactive
(响应式应用) 或None
(非 Web 应用) - 利用 Spring Factories 机制从
META-INF/spring.factories
文件中加载ApplicationContextInitializer
和ApplicationListener
3. 获取并启动监听器
加载并实例化 spring.factories
中定义的监听器(实现类主要是 EventPublishingRunListener
),进行广播 ApplicationStartingEvent
事件。 通知所有感兴趣的 ApplicationListener
应用即将开始启动。
4. 准备环境
- 创建运行时环境
Environment
,处理命令行参数和application.properties/application.yml
配置文件加载环境变量 - 广播
ApplicationEnvironmentPreparedEvent
事件,通知监听器环境已准备就绪
5. 创建 ApplicationContext
创建 ApplicationContext
:
- 注册包含主配置类(
@SpringBootApplication
)在内的所有配置类(@Configuration
) - 广播
ApplicationPreparedEvent
事件,这时ApplicationContext
已经创建完成,但还未refresh
(刷新),可以对其进行最后的修改
6. 刷新 ApplicationContext
调用 AbstractApplicationContext
的 refresh()
方法,这是最复杂也是最关键的一步,是 Spring 容器初始化 Bean 的核心流程:
- 创建并初始化所有定义的单例 Bean
- BeanPostProcessor 干预 Bean 的创建过程:依赖注入、创建 AOP 代理对象
- 启动嵌入式 Web 服务器
7. 执行 CommandLineRunner
和 ApplicationRunner
- 应用启动后,会先按
@order
顺序执行ApplicationRunner
和CommandLineRunner
- 我们一般会在
ApplicationRunner
或CommandLineRunner
中执行自定义的初始化逻辑,比如:缓存预热、加载初始化数据等
8. 应用启动完成,发布 ready 事件,正式开始处理业务请求或任务
SpringBoot 如何实现缓存预热
- 基于 SpringBoot 的启动流程,我们可以通过
ApplicationRunner
或CommandLineRunner
实现缓存预热,比如:
SpringBoot 应用启动后将 Mysql 数据缓存入 Redis
@Component
public class CacheLoader implements CommandLineRunner {
@Autowired
private MySqlRepository repository;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public void run(String... args) {
List<MsgDO> data = repository.list();
redisTemplate.opsForValue().set("key", data);
}
}
- 也可以通过
@PostConstruct
注解实现
自动配置原理
SpringBoot 的自动配置是通过 @EnableAutoConfiguration
实现的,这个注解包含 @Import(AutoConfigurationImportSelector.class)
注解, 导入的这个类会去扫描 classpath
下所有的 META-INF/spring.factories
文件,根据文件中的内容加载相应的 Bean 。
这些 Bean 通常会使用 @ConditionalOnClass
、@ConditionalOnMissingBean
、@ConditionalOnProperty
等条件注解来控制是否进行加载。
自动配置顺序
SpringBoot 提供了 @AutoConfigurationBefore
和 @AutoConfigurationAfter
注解来控制自动配置类的加载顺序
@Configuration
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
public class MyDataSourceAutoConfiguration {
// 自定义的数据源配置
}
禁用特定的自动配置
如果 SpringBoot 的默认自动配置和我们的实际业务需求不符,可以禁用掉部分自动配置内容
- 在
application.properties
中添加spring.autoconfigure.exclude
属性,指定要排除的配置类
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- 也可以使用
@SpringBootApplication
注解的exclude
属性
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
SpringBoot 事件机制
在之前的 SpringBoot 启动流程中就已经提到了大量的事件发布与监听。SpringBoot 的事件机制是基于观察者模式实现的,主要流程如下:
- 事件发布:事件通过
ApplicationEventPublisher
发布,发布者不需要关心事件的处理细节 - 事件监听:
ApplicationEventMulticaster
会把事件分发给所有的监听器,监听器ApplicationListener
接收事件 - 异步处理:如果监听器使用了
@Async
,事件会被异步处理,不影响主线程的执行
SpringBoot 有许多内置事件,比如:
ApplicationStartingEvent
:应用启动开始ApplicationEnvironmentPreparedEvent
:环境准备完成(解析了application.yml
、命令行参数等)ApplicationContextInitializedEvent
:应用上下文已创建完毕,但还未加载 Bean 定义ApplicationPreparedEvent
:应用上下文已加载 Bean 定义,但 Bean 尚未实例化 (refresh
)ApplicationStartedEvent
:容器已刷新完成,且所有ApplicationRunner
和CommandLineRunner
执行完毕ApplicationReadyEvent
(最重要):应用已完全就绪,都可以开始接收服务请求,此时健康检查/actuator/health
状态为UP
ApplicationFailedEvent
:启动过程中发生异常导致失败时
自定义监听器,监听内置事件:
也可以监听具体指定事件,如指定 ApplicationEnvironmentPreparedEvent
环境准备就绪事件:
@Component
public class DbConfigListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
// 此时环境已经准备就绪,可以获取环境变量了
}
}
自定义事件
我们也可以自定义事件,利用事件驱动机制实现自定义需求,比如当用户登录成功后,自动签到加积分:
- 创建登录成功事件
public class LoginSuccessEvent extends ApplicationEvent {
public LoginSuccessEvent(UserEntity source) {
super(source);
}
}
- 创建事件推送器
@Service
public class EventPublisher implements ApplicationEventPublisherAware {
/**
* 底层发送事件用的组件,事件是广播出去的,所有监听这个事件的监听器都可以收到
*/
ApplicationEventPublisher applicationEventPublisher;
public void sendEvent(ApplicationEvent event) {
System.out.println("发布事件");
applicationEventPublisher.publishEvent(event);
}
/**
* 会被自动调用,把真正发事件的底层组件给我们注入进来
* @param applicationEventPublisher event publisher to be used by this object
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
- 监听事件,事件触发时进行加积分
@Service
public class AccountService {
public void addAccountScore(String username) {
System.out.println(username + " 加了1分");
}
// 监听 LoginSuccessEvent 事件
@EventListener
public void onEvent(LoginSuccessEvent event) {
UserEntity user = (UserEntity) event.getSource();
addAccountScore(user.getUsername());
}
}
- 登录成功时,进行事件推送
@Tag(name = "用户管理",description = "用户管理")
@RequestMapping("/user")
@RestController
public class UserRestController {
@Resource
EventPublisher eventPublisher;
@Operation(summary = "用户登录")
@GetMapping("/login")
public SaResult login(@RequestParam(value = "username")String username,@RequestParam("password") String password) {
String sha256 = SaSecureUtil.sha256(password);
//模拟直接登录成功 (用的 Sa-Token)
StpUtil.login(1111);
//1、创建登录成功事件
LoginSuccessEvent loginSuccessEvent = new LoginSuccessEvent(new UserEntity(username, sha256));
//2、发送事件
eventPublisher.sendEvent(loginSuccessEvent);
return SaResult.ok();
}
}
探针机制
事件机制是 SpringBoot 系统内部主动推送状态变更,探针(actuator
) 机制则是让外部(K8S、云服务)感知应用内部的健康状态。
spring-boot-starter-actuator
关键端点(Endpoints
)主要有:
/actuator/health
:健康检查,UP
表示健康, HTTP 状态码为200
;DOWN
标识为不健康, HTTP 状态码为503
(K8s 据此重启容器)/actuator/info
:展示构建信息、Git 提交等静态信息/actuator/metrics
:暴露 JVM、系统指标 (可用于对接Prometheus
+Grafana
)
/actuator/health
端点有两个关键探针:
- 存活探针(
liveness
):检查容器是否应该重启,比如死锁、关键资源耗尽;若失败,K8s 会重启该Pod
- 就绪探针(
readiness
):检查容器是否准备好接收流量(如缓存是否预热完、数据库连接已建立);若失败,K8s 不暂时不会把流量路由到该Pod
引入探针模块
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 暴露端点,可在
application.yml
配置
# 暴露所有监控端点
management:
endpoints:
web:
exposure:
include: '*'
- 访问
http://localhost:8080/actuator
可以看到所有暴露的端点
定制 Health 端点
- 实现
HealthIndicator
接口或继承AbstractHealthIndicator
@Component
public class MyHealthIndicator extends AbstractHealthIndicator {
@Autowired
MyComponent myComponent;
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
//自定义检查方法
int check = myComponent.check();
if (check == 1) {
builder.up()
.withDetail("code",1000)
.withDetail("msg","活得很健康")
.withDetail("data","我是组件哈哈哈哈")
.build();
}else {
builder.down().build();
}
}
}
@Component
public class MyComponent {
public int check() {
//业务代码判断这个组件是否该是存活状态
return 1;
}
}
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 模拟某个组件健康检查方法,需要自定义
boolean check = MyComponent.check();
// 根据健康检查结果自定义响应
if (check) {
return Health.up()
.withDetail("code",200)
.build();
}else {
return Health.down()
.withDetail("code",500)
.build();
}
}
}
- 修改
application
配置文件展示详细信息
management:
endpoint:
health:
enabled: true
show-details: always
- 测试结果
定制 Metrics 端点
我们也可以定制 Metrics 端点来自定义监控指标,比如记录某个组件的调用次数
- 对要创建的组件注入
MeterRegistry
@Component
public class MyComponent {
Counter counter = null;
public MyComponent(MeterRegistry meterRegistry) {
//得到一个名为 myComponent.check 的计数器
counter = meterRegistry.counter("myComponent.check");
}
public int check() {
//每被调用一次,计数器+1
counter.increment();
//业务代码判断这个组件是否该是存活状态
return 1;
}
}
- 编写
Controller
层接口进行测试
@RequestMapping("/my")
@RestController
public class MyController {
@Autowired
MyComponent myComponent;
@GetMapping("/hello")
public String hello() {
myComponent.check();
return "哈哈哈";
}
}
- 访问若干次后(对用户无感),查看
actuator/metrics/myComponent.check
整合 Prometheus + Grafana
前面说了引入 spring-boot-starter-actuator
模块,即可对外暴露大量的系统内部监控指标数据,但这些数据是 json
格式的
这种数据前端展示不够友好,因此我们可以使用 Prometheus
+ Grafana
来进行指标数据的可视化展示。
Promethus
是一个时序数据库,因此需要单独引入相关依赖,将监控指标数据转换为 Prometheus
支持的格式。
- 创建项目
引入micrometer-registry-prometheus
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 将项目打包并且部署到服务器上
我使用的是我自己的云服务器来进行部署测试,包括 Prometheus
和 Grafana
都是部署在我的云服务器上。如果没有 JDK 环境需要先安装 JDK 环境。
# 下载 jdk 21
wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz
mkdir -p /opt/java
# 解压
tar -xzf jdk-21_linux-x64_bin.tar.gz -C /opt/java/
#配置环境变量
vi /etc/profile
#添加
export JAVA_HOME=/opt/java/jdk-21.0.5
export PATH=$PATH:$JAVA_HOME/bin
# 让环境变量更改生效
source /etc/profile
# 后台启动 java 应用
nohup java -jar app.jar > output.log 2>&1 &
- 安装
Prometheus + Grafana
我使用 docker 的方式进行安装,Grafana
安装十分简单,默认账号密码为 admin:admin
# 安装 grafana , 默认账号密码 admin:admin
docker run -d --name=grafana -p 3000:3000 grafana/grafana
Prometheus
需要创建配置文件(/opt/promethues/conf/prometheus.yml
),指定要拉取的数据源
global:
# 设置默认的数据抓取间隔为 15 s
scrape_interval: 15s
# 设置默认的告警规则评估间隔为 15 s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'spring-boot-demo'
# spring-boot 的 Prometheus 指标路径
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['8.140.207.120:8080']
labels:
nodename: 'app-demo'
然后使用 docker 启动 Prometheus
# 安装 prometheus 时序数据库
docker run \
--name=prometheus \
-d \
-p 9090:9090 \
-v /opt/prometheus/conf:/etc/prometheus \
prom/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/prometheus \
--web.console.libraries=/usr/share/prometheus/console_libraries \
--web.console.templates=/usr/share/prometheus/consoles \
--web.enable-lifecycle
然后在 Grafana
面板中添加 Prometheus
数据源
最后为 Grafana
添加一个前端展示模板 dashboard
,就可以展示从 Prometheus
采集到的数据了
配置相关
配置文件的优先级
对常用配置优先级,从高到低排序:
- 命令行参数
- Jar 包外的
application.properties
文件 - Jar 包内的
application.properties
文件
补充
application-{profile}.properties
优先级高于application.properties
application.properties
优先级高于application.yml
官方文档完整配置优先级
定义和读取自定义配置
SpringBoot 定义和读取自定义配置主要有三种方式:
@Value("${my.custom.property}")
private String myProperty;
@Component
@ConfigurationProperties(prefix = "my.custom")
public class MyCustomProperties {
private String property;
}
@Autowired
private Environment env;
public void someMethod() {
String value = env.getProperty("my.custom.property");
}
多数据源配置
我们的应用中往往需要使用不同的数据源,那么如何实现多数据源配置呢?
- 在
application.yml
配置文件中为不同的数据源定义连接信息
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/primary_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
- 为每个数据源分布配置
DataSource
、SqlSessionFactory
和TransactionManager
,并为主数据源标记@Primary
@Configuration
@MapperScan(basePackages = "com.example.primary.mapper", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean.getObject();
}
@Primary
@Bean(name = "primaryTransactionManager")
public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@Configuration
@MapperScan(basePackages = "com.example.secondary.mapper", sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
return sessionFactoryBean.getObject();
}
@Bean(name = "secondaryTransactionManager")
public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
- 使用
@MapperScan
为每个数据源独立指定Mapper
扫描路径,并绑定相应的SqlSessionFactory
@Configuration
@MapperScan(basePackages = "com.example.primary.mapper", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
// 主数据源配置
}
@Configuration
@MapperScan(basePackages = "com.example.secondary.mapper", sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {
// 次数据源配置
}
- 可以通过
@Transactional
注解指定相应的事务管理器
@Service
public class MyService {
@Autowired
private PrimaryMapper primaryMapper;
@Autowired
private SecondaryMapper secondaryMapper;
@Transactional(transactionManager = "primaryTransactionManager")
public void usePrimaryDataSource() {
primaryMapper.insertData(...);
}
@Transactional(transactionManager = "secondaryTransactionManager")
public void useSecondaryDataSource() {
secondaryMapper.insertData(...);
}
}
日志配置
SpringBoot 底层默认使用 logback
作为日志框架,不过也可以切换为其他日志框架
切换日志框架
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 导入 spring-boot-starter 就近原则,优先级高于
spring-boot-starter-web 依赖的 spring-boot-starter -->
<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>
<!-- 使用性能更好的 log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
- SpringBoot 如何实现默认日志配置?
1、每个 starter
场景,都会引入一个核心场景 spring-boot-starter
2、核心场景引入了日志配置 spring-boot-starter-logging
3、默认使用了 logback
+ slf4j
组合作为默认底层日志 4、日志是系统一启动就要用, xxxAutoConfiguration
是系统启动好了之后放进去的组件,因此日志是用监听器机制配置的 ApplicationListener
5、日志的所有功能都可以通过修改配置文件来实现
- 如何设置日志级别、分组、文件输出等?
在 application.properties
中设置日志级别、分组和文件输出
#默认所有日志没有精确指定级别就使用 root 的默认级别
logging.level.root=debug
#也可以精确指定某个包或者类的日志级别
logging.level.com.xxx.xxx=debug
# 将多个包分为同一个组
logging.group.xxx=com.xxx.xxx,com.xxx.xxx
# 对一个组设置日志级别
logging.level.xxx=debug
# springboot 默认为我们提供了 web 和 sql 组
logging.level.web=debug
logging.level.sql=debug
# 只写名字,默认生成在当前项目同位置的 demo.log 中
logging.file.name=demo.log
# 写名字 + 路径
logging.file.name=/opt/applog/demo.log
logback
通过application.yml
设置日志文件归档
logging:
logback:
rollingpolicy:
# 滚动策略配置,默认每天一个,超过单个文件最大 size 进行切割
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz
# 单个日志文件的最大大小,默认为 10M
max-file-size: 10MB
# 应用启动时是否清楚以前文档,默认值 false
clean-history-on-start: false
# 日志文件被删除前,可以容纳的最大大小,默认为 0B,如果设置 1G,则磁盘存储超过1G后会删除旧日志文件
total-size-cap: 0B
# 保存的最大历史文件天数,默认为 7天
max-history: 7
file:
name: /opt/applog/my.log
日志最佳实践
- 导入第三方框架,可以先排除它的日志包,因为 Boot 底层统一控制了日志管理
- 修改
application.yml
配置,就可以调整日志的所有行为,也可以编写日志框架本身的配置文件,如logback-spring.xml