Spring Boot 日志 ------- 13

 

「基础日志打印 → 级别控制 → 生产级文件滚动归档」全覆盖。Spring Boot 内置 SLF4J + Logback,只要引入了 spring-boot-starter-web 就自带,无需额外依赖,复制即可用。

一、前置说明(对应 143 集:日志的重要性)

日志是线上排查问题、开发调试的核心手段,作用通俗来讲:
  • 开发阶段:看程序执行流程、定位 Bug
  • 线上环境:追溯故障、统计异常、监控系统状态
  • 分级输出:开发打详细日志,生产只打关键信息,兼顾性能和可排查性

日志级别(从低到高,输出内容依次减少)

TRACE < DEBUG < INFO < WARN < ERROR
  • Spring Boot 默认级别:INFO,默认只输出 INFO、WARN、ERROR 三级
  • 级别越低,打印内容越多;级别越高,只打印严重问题

二、基础日志使用(对应 144、145 集)

1. 代码中打印日志(两种写法,推荐第二种)

方式 1:手动创建 Logger(不依赖 Lombok)

java
 
运行
 
 
package com.example.jobportal.service;

import com.example.jobportal.dto.ContactDTO;
import com.example.jobportal.entity.Contact;
import com.example.jobportal.exception.BusinessException;
import com.example.jobportal.repository.ContactRepository;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ContactService {

    // 1. 创建日志对象,绑定当前类
    private static final Logger log = LoggerFactory.getLogger(ContactService.class);

    private final ContactRepository contactRepository;

    public Contact saveContact(ContactDTO dto) {
        // 各级别日志示例
        log.trace("【TRACE】进入方法,完整参数:{}", dto);
        log.debug("【DEBUG】开始处理留言,用户邮箱:{}", dto.getEmail());
        log.info("【INFO】用户提交留言,姓名:{}", dto.getName());

        // 业务校验
        if (dto.getMessage().contains("测试垃圾内容")) {
            log.warn("【WARN】检测到违规内容,提交人:{}", dto.getName());
            throw new BusinessException("请勿提交违规内容");
        }

        try {
            Contact contact = new Contact();
            contact.setName(dto.getName());
            contact.setEmail(dto.getEmail());
            contact.setMessage(dto.getMessage());
            Contact saved = contactRepository.save(contact);
            log.info("【INFO】留言保存成功,记录ID:{}", saved.getId());
            return saved;
        } catch (Exception e) {
            // 异常必须第二个参数传异常对象,才能打印完整堆栈
            log.error("【ERROR】留言保存失败", e);
            throw e;
        }
    }
}

 

 

方式 2:Lombok @Slf4j 注解(最简写法,推荐)

加一个注解就自动生成 log 对象,不用手动写工厂类
java
 
运行
 
 
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ContactService {
    public void test() {
        // 直接使用 log 对象,和上面效果完全一致
        log.info("一行注解搞定日志");
    }
}
 

 

💡 占位符说明:用 {} 代替字符串拼接,性能更好、写法更简洁,是行业通用最佳实践。

2. application.properties 基础配置

控制日志级别、输出格式
properties
 
 
# ========== 日志级别 ==========
# 根日志默认级别,生产建议INFO,开发可改DEBUG
logging.level.root=INFO

# 单独指定包的级别(精细控制)
logging.level.com.example.jobportal=DEBUG
logging.level.org.springframework.web=INFO
logging.level.org.hibernate.SQL=DEBUG # 打印SQL语句,调试JPA非常好用

# ========== 控制台输出格式 ==========
# %d时间 %-5level级别左对齐 %thread线程名 %logger类名 %msg消息 %n换行
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} : %msg%n

 

 

三、生产级日志配置(对应 146 集:Logback Appenders)

application.properties 只能做基础配置,生产环境统一用 logback-spring.xml 实现高级功能:
  • 控制台彩色输出
  • 日志写入文件,按天自动拆分
  • 超过大小自动压缩归档
  • 自动清理过期日志
  • 错误日志单独存文件,方便排查

新建文件:src/main/resources/logback-spring.xml

Spring Boot 会自动识别加载
xml
 
 
<?xml version="1.0" encoding="UTF-8"?>
<!-- scan=true:配置文件修改后自动热加载,不用重启项目 -->
<configuration scan="true" scanPeriod="60 seconds">

    <!-- 定义公共变量:日志存放路径、项目名 -->
    <property name="LOG_PATH" value="./logs"/>
    <property name="APP_NAME" value="jobportal"/>

    <!-- ========== 1. 控制台输出 Appender ========== -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 彩色格式:不同级别不同颜色,开发调试更直观 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) [%thread] %cyan(%logger{36}) : %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- ========== 2. 全量日志滚动文件 Appender ========== -->
    <!-- 按天+按大小滚动,自动压缩归档,自动清理旧日志 -->
    <appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 当前正在写入的日志文件名 -->
        <file>${LOG_PATH}/${APP_NAME}.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档文件命名:日期+序号,压缩成gz格式 -->
            <fileNamePattern>${LOG_PATH}/${APP_NAME}.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <!-- 保留最近30天日志 -->
            <maxHistory>30</maxHistory>
            <!-- 所有日志总大小不超过5GB,超过自动删最老的 -->
            <totalSizeCap>5GB</totalSizeCap>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 单个文件最大100MB,超过就拆分新文件 -->
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} : %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- ========== 3. 错误日志单独文件 ========== -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/${APP_NAME}-error.log</file>
        <!-- 过滤器:只接收ERROR级别日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/${APP_NAME}-error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <maxHistory>90</maxHistory> <!-- 错误日志保留90天 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>50MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} : %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- ========== 4. 总配置:按环境区分 ========== -->
    <!-- 开发环境:控制台+文件都输出,级别低信息多 -->
    <springProfile name="default,dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
            <appender-ref ref="ALL_FILE"/>
            <appender-ref ref="ERROR_FILE"/>
        </root>
    </springProfile>

    <!-- 生产环境:只写文件,级别调高,减少性能损耗 -->
    <springProfile name="prod">
        <root level="WARN">
            <appender-ref ref="ALL_FILE"/>
            <appender-ref ref="ERROR_FILE"/>
        </root>
    </springProfile>

</configuration>

 

 

四、核心概念通俗解释

1. 什么是 Appender?(146 集核心)

就是「日志输出到哪里」的策略,一个日志可以同时输出到多个地方:
  • ConsoleAppender:输出到控制台,开发调试用
  • RollingFileAppender:输出到文件,自动滚动拆分,避免单个文件几十 GB 打不开

2. 滚动策略是什么?

  • 按时间滚动:每天生成新文件,按日期查日志非常方便
  • 按大小滚动:单文件超过上限就拆分,避免大文件打不开
  • 自动压缩:历史日志存成 .gz 压缩包,大幅节省磁盘
  • 自动清理:超过保留天数自动删除,不用手动清理

3. 多环境切换

通过 springProfile 标签区分开发 / 生产:
  • 开发:控制台 + 文件双输出,级别低,信息全
  • 生产:只写文件,只打警告和错误,兼顾性能和排查能力

五、课程对应表

表格
 
集数核心内容对应部分
143 日志的价值:调试与监控支柱 前置说明 + 最佳实践
144、145 日志基础使用演示 代码日志打印 + application.properties 配置
146 生产级日志设计,Logback Appenders logback-spring.xml 滚动、归档、多环境配置

六、通用最佳实践

  1. 禁止用 System.out.println:无法分级、无法归档、性能差
  2. 异常必须打堆栈:log.error("描述", e),第二个参数传异常对象,才能看到完整报错链
  3. 用占位符 {}:不要字符串拼接,避免不必要的性能损耗
  4. 敏感信息脱敏:密码、手机号、身份证不要明文打日志
  5. 生产不开 DEBUG:日志量会爆炸,严重影响性能、占用磁盘

 

 

posted @ 2026-08-01 01:40  漫漫长路</>  阅读(4)  评论(0)    收藏  举报