日志怎么打才专业?Spring Boot 4 日志体系与 Logback 配置(生产级实战)

本篇是《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 logbacklog4j 的类!


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 句话)

  1. Spring Boot 4 = SLF4J + Logback

  2. 生产环境必须写日志文件

  3. 日志要滚动、压缩、清理

  4. 异步日志提升性能

  5. 异常日志一定要带堆栈

相关推荐
卷无止境1 小时前
FastAPI CLI 你需要认识这把命令行利器
后端·python·fastapi
SaaS发言人1 小时前
渠道数字化解决方案横评:谁更懂快消
java·大数据·人工智能
JL151 小时前
Java并发编程面试全攻略-从synchronized到AQS底层原理
java·开发语言·面试·并发编程
ZC跨境爬虫1 小时前
LeetCode 119. 杨辉三角 II(原地更新优化详解 + Java Python 实现)
java·python·leetcode
AINative软件工程1 小时前
LLM 请求合并工程实践:用 Single-Flight 把并发重复调用从 N 次砍成 1 次
后端·llm·ai编程
程序员爱钓鱼1 小时前
Go 编程实战:数组 Array——固定长度的数据集合
后端·面试·go
程序员黑豆7 小时前
Java包装类:基本类型与对象的桥梁
java·前端·ai编程
桦说编程9 小时前
并发编程中的等待-通知模式:从 wait/notify 到 Guava Monitor
后端