本篇是《Spring Boot 4 学习从入门到大神》专栏第 5 篇。
很多项目"能跑,但日志一塌糊涂"。本文将彻底讲清 Spring Boot 4 的日志架构、Logback 配置、日志分级、文件滚动和生产环境最佳实践,帮你写出可排查、可审计、可运维的日志。
一、Spring Boot 4 日志体系全景图
Spring Boot 4 默认日志方案:
SLF4J → Logback
1️⃣ 为什么是 SLF4J?
SLF4J 只是一个日志门面,不是实现。
✅ 好处:
-
不绑定具体日志框架
-
随时切换实现(Log4j2 / Logback)
-
代码无侵入
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class DemoService {
private static final Logger log = LoggerFactory.getLogger(DemoService.class);
}
📌 永远不要直接 import logback 或 log4j 的类!
2️⃣ Spring Boot 4 默认实现:Logback
Spring Boot Starter 中已内置:
spring-boot-starter-logging
它包含:
-
SLF4J
-
Logback
-
桥接器(jul-to-slf4j、log4j-to-slf4j)
✅ 你什么都不用配,日志就能用。
二、日志级别(必须分清)
Spring Boot 4 支持以下级别(从低到高):
| 级别 | 使用场景 |
|---|---|
TRACE |
最细粒度,调试底层 |
DEBUG |
开发调试 |
INFO |
关键业务节点(推荐) |
WARN |
潜在问题 |
ERROR |
错误,但系统还能跑 |
FATAL |
严重错误,系统即将崩溃(Logback 不常用) |
📌 生产环境默认级别:INFO
三、最简单也最正确的打日志方式
✅ 推荐写法(占位符)
log.info("用户 {} 登录成功,IP={}", userId, ip);
❌ 错误写法(字符串拼接)
log.info("用户 " + userId + " 登录成功,IP=" + ip);
❌ 缺点:
-
即使日志级别不生效,字符串也会拼接
-
影响性能
四、Spring Boot 4 日志基础配置(application.yml)
1️⃣ 全局日志级别
logging:
level:
root: INFO
com.example.demo: DEBUG
org.springframework: WARN
✅ 含义:
-
全局:
INFO -
自己项目:
DEBUG -
Spring 框架:
WARN
2️⃣ 输出到文件(生产必配)
logging:
file:
name: logs/app.log
format:
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n"
📌 不要只打控制台日志!
五、为什么默认配置不够用?(生产痛点)
默认配置的问题:
-
❌ 日志文件无限增长
-
❌ 不按日期切割
-
❌ 不压缩
-
❌ 排查问题时找不到日志
👉 生产环境必须使用 logback-spring.xml
六、生产级 logback-spring.xml 配置(重点)
在 src/main/resources 下创建:
logback-spring.xml
✅ 完整示例(可直接复制)
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 引入 Spring Boot 默认配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 日志文件路径 -->
<property name="LOG_PATH" value="logs"/>
<property name="APP_NAME" value="spring-boot4-demo"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 文件输出(按天滚动) -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/${APP_NAME}.log</file>
<!-- 滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天归档 -->
<fileNamePattern>${LOG_PATH}/${APP_NAME}.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
<!-- 保留 30 天 -->
<maxHistory>30</maxHistory>
<!-- 总大小不超过 3GB -->
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 异步日志(提升性能) -->
<appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="FILE"/>
<!-- 队列满时丢弃 TRACE、DEBUG -->
<discardingThreshold>0</discardingThreshold>
<queueSize>512</queueSize>
</appender>
<!-- 环境隔离:dev 只打控制台 -->
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<!-- 生产环境:文件 + 异步 -->
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ASYNC_FILE"/>
</root>
</springProfile>
</configuration>
七、这个配置强在哪?(重点理解)
✅ 按天滚动 :app.2026-01-15.log.gz
✅ 自动压缩:节省磁盘
✅ 自动清理:只保留 30 天
✅ 异步写日志:不阻塞业务线程
✅ 环境隔离:dev / prod 不同策略
八、多环境日志配置(Spring Boot 4 特色)
利用 springProfile:
<springProfile name="dev">
<!-- 开发环境 -->
</springProfile>
<springProfile name="prod">
<!-- 生产环境 -->
</springProfile>
✅ 比 application.yml 更灵活
九、日志打印的最佳实践(非常重要)
✅ 1️⃣ 哪些必须打日志?
-
系统启动 / 关闭
-
关键业务操作(下单、支付、登录)
-
外部接口调用(入参 + 出参)
-
异常堆栈(不要吞掉)
✅ 2️⃣ 哪些不要打?
❌ 敏感信息(密码、身份证、Token)
❌ 大对象(JSON 全量打印)
❌ 高频循环内打日志
✅ 3️⃣ 异常日志怎么打?
❌ 错误写法:
log.error("出错了:" + e.getMessage());
✅ 正确写法:
log.error("用户 {} 下单失败", userId, e);
📌 一定要把异常对象传进去!
十、Spring Boot 4 中的日志新变化
-
日志初始化更早(AOT 模式)
-
对 GraalVM 原生镜像支持更好
-
日志桥接器默认更严格(防止冲突)
十一、常见坑位总结
❌ 坑1:日志文件把磁盘打满
✅ 解决:配置滚动策略 + 总大小限制
❌ 坑2:生产环境只打控制台
✅ 解决:必须输出到文件
❌ 坑3:异常没堆栈
✅ 解决:log.error("msg", e)
❌ 坑4:直接使用 System.out.println
✅ 解决:统一用 SLF4J
十二、本篇总结(记住这 5 句话)
-
Spring Boot 4 = SLF4J + Logback
-
生产环境必须写日志文件
-
日志要滚动、压缩、清理
-
异步日志提升性能
-
异常日志一定要带堆栈