---
URL: "/zh-CN/blog/2026-03/spring-boot-log.html"
LLMS_URL: "/zh-CN/blog/2026-03/spring-boot-log.md"
lastUpdated: true
commentabled: true
recommended: true
title: "Spring Boot日志配置实战"
description: "Logback vs Log4j2-Spring全解析"
date:

pageClass: "blog-page-class"
cover: "/covers/springboot.svg"
---

---
lastUpdated: true
commentabled: true
recommended: true
title: Spring Boot日志配置实战
description: Logback vs Log4j2-Spring全解析
date: 2026-03-06 10:45:00 
pageClass: blog-page-class
cover: /covers/springboot.svg
---

在Spring Boot开发中，日志就像系统的“黑匣子”，既能帮我们排查线上bug，又能监控系统运行状态。但很多同学在面对`Logback`和`Log4j2-Spring`这两种主流日志框架时，总会陷入“该选哪个？怎么配置？”的困惑。

今天这篇文章，我会从实战角度出发，手把手教你配置`Logback`和`Log4j2-Spring`，再深度剖析二者的核心区别，帮你在实际开发中精准选型。话不多说，直接上干货！

## 一、前置认知：Spring Boot日志体系基础 ##

在讲具体配置前，先明确一个关键知识点：Spring Boot默认使用*SLF4J*作为日志门面（负责日志API定义），而Logback是默认的日志实现。这也是为什么我们新建Spring Boot项目后，不用额外引入依赖就能直接用日志的原因。

而Log4j2-Spring是另一种高性能的日志实现，需要我们手动排除默认的Logback依赖并引入Log4j2相关依赖。这里先放一张核心关系图帮大家理解：

SLF4J（门面） → 日志实现（Logback/Log4j2） → 输出日志（控制台/文件/数据库等）

小贴士：日志门面的优势在于解耦，后续想切换日志实现时，不用修改业务代码，只需要更换依赖和配置文件即可。

## 二、Logback日志配置实战（默认首选） ##

既然Spring Boot默认集成Logback，那我们先从它入手。Logback的配置核心是`logback-spring.xml`（推荐用这个命名，支持Spring Boot的profile多环境配置），放在`resources`目录下即可生效。

### 基础依赖（无需额外引入） ###

Spring Boot的`spring-boot-starter`已经包含了`spring-boot-starter-logging`，而后者默认集成了Logback和SLF4J，所以新建项目后直接就能用。

### 核心配置文件（logback-spring.xml） ###

下面是一个生产级别的基础配置，包含控制台输出、文件滚动输出、多环境适配、日志级别控制等核心功能，每一步都加了注释，新手也能看懂：

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Logback配置根节点，scan开启配置自动扫描，scanPeriod扫描间隔30秒 -->
<configuration scan="true" scanPeriod="30 seconds">
    
    <!-- 定义日志输出格式变量，包含时间、线程、级别、日志器、消息等信息 -->
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />
    <!-- 定义日志存储路径变量，指定日志文件存放的目录 -->
    <property name="LOG_PATH" value="logs/spring-boot-logback" />

    
    <!-- 控制台输出器配置，指定输出到控制台 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 编码器配置，控制日志输出格式和字符集 -->
        <encoder>
            <!-- 引用上面定义的日志格式变量 -->
            <pattern>${LOG_PATTERN}</pattern>
            <!-- 设置日志输出字符集为UTF-8，避免中文乱码 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    
    <!-- 普通信息日志文件输出器，采用滚动策略（RollingFileAppender） -->
    <appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <!-- 指定当前日志文件的路径和名称 -->
        <file>${LOG_PATH}/info.log</file>
        
        <!-- 滚动策略：基于时间的滚动策略（每天生成一个日志文件） -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            
            <!-- 归档日志文件的命名格式，包含日期信息 -->
            <fileNamePattern>${LOG_PATH}/info-%d{yyyy-MM-dd}.log</fileNamePattern>
            
            <!-- 日志文件保留天数，超过30天的归档日志会自动删除 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        
        <!-- 日志级别过滤器，只允许INFO级别的日志通过 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <!-- 指定过滤的日志级别为INFO -->
            <level>INFO</level>
            <!-- 匹配到INFO级别日志时接受输出 -->
            <onMatch>ACCEPT</onMatch>
            <!-- 未匹配到INFO级别日志时拒绝输出 -->
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 编码器配置，与控制台输出器一致，保证格式统一 -->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    
    <!-- 错误日志文件输出器，单独分离错误日志便于排查 -->
    <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 当前错误日志文件的路径和名称 -->
        <file>${LOG_PATH}/error.log</file>
        <!-- 同样采用基于时间的滚动策略 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 错误归档日志的命名格式 -->
            <fileNamePattern>${LOG_PATH}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 错误日志同样保留30天 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <!-- 过滤器：只允许ERROR级别的日志通过 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <!-- 编码器配置 -->
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    
    <!-- 开发环境（dev）日志配置，通过springProfile标签适配多环境 -->
    <springProfile name="dev">
        <!-- 根日志器配置，日志级别为INFO -->
        <root level="INFO">
            <!-- 开发环境只输出到控制台，便于开发调试 -->
            <appender-ref ref="CONSOLE" />
        </root>
    </springProfile>

    <!-- 生产环境（prod）日志配置 -->
    <springProfile name="prod">
        <!-- 根日志器级别为INFO -->
        <root level="INFO">
            <!-- 生产环境同时输出到控制台和文件，便于实时查看和归档 -->
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="FILE_INFO" />
            <appender-ref ref="FILE_ERROR" />
        </root>
        
        <!-- 单独配置MyBatis的Mapper接口日志级别为DEBUG，便于查看SQL执行详情 -->
        <logger name="com.xxx.mapper" level="DEBUG" additivity="false">
            <!-- additivity="false"表示不向上级日志器传递，避免重复输出 -->
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="FILE_INFO" />
        </logger>
    </springProfile>
</configuration>
```

### 代码中使用Logback ###

通过SLF4J的LoggerFactory获取日志对象，无需直接依赖Logback的API，符合门面模式的最佳实践：

```java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogTestController {
    // 获取日志对象（传入当前类的Class）
    private static final Logger logger = LoggerFactory.getLogger(LogTestController.class);

    @GetMapping("/testLog")
    public String testLog() {
        logger.trace("这是TRACE级别的日志");
        logger.debug("这是DEBUG级别的日志");
        logger.info("这是INFO级别的日志");
        logger.warn("这是WARN级别的日志");
        logger.error("这是ERROR级别的日志");
        return "日志测试成功";
    }
}
```

启动项目后访问接口，就能在控制台（dev环境）或日志文件（prod环境）中看到对应的日志输出了。

## 三、Log4j2-Spring日志配置实战（高性能之选） ##

Log4j2是Apache推出的新一代日志框架，相比Logback在异步日志、高并发场景下的性能更优。但由于Spring Boot默认集成Logback，所以使用Log4j2需要先排除默认依赖，再引入相关依赖。

### 依赖配置（Maven为例） ###

在`pom.xml`中排除Logback依赖，并引入Log4j2的starter：

```xml
<!-- 项目依赖总节点 -->
<dependencies>
    <!-- Spring Boot Web场景启动器，集成了Web开发核心依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        
        <!-- 排除默认集成的Logback日志依赖，避免与Log4j2冲突 -->
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <!-- Spring Boot默认的日志启动器，内置Logback -->
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    
    <!-- 引入Log4j2的Spring Boot专用启动器，集成SLF4J门面 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

    
    <!-- 引入Disruptor框架，用于支持Log4j2的高性能异步日志 -->
    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.4.4</version><!-- 稳定版本，适配主流Log4j2版本 -->
    </dependency>
</dependencies>
```

### 核心配置文件（log4j2-spring.xml） ###

Log4j2的配置文件支持XML、JSON、YAML等格式，这里以最常用的XML为例，配置功能和Logback对应，方便大家对比学习：

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Log4j2配置根节点，status指定自身日志级别为INFO，monitorInterval30秒自动刷新配置 -->
<Configuration status="INFO" monitorInterval="30">
    
    <!-- 配置属性节点，定义日志格式和路径变量，与Logback逻辑一致 -->
    <Properties>
        <!-- 日志输出格式变量，包含时间、线程、级别等关键信息 -->
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</Property>
        <!-- 日志存储路径变量 -->
        <Property name="LOG_PATH">logs/spring-boot-log4j2</Property>
    </Properties>

    
    <!-- 输出器（Appenders）配置节点，定义日志的输出目的地 -->
    <Appenders>
        
        <!-- 控制台输出器，target指定输出到标准输出流（SYSTEM_OUT） -->
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <!-- 模式布局器，指定日志格式和字符集 -->
            <PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
        </Console>

        
        <!-- 普通信息滚动文件输出器，fileName指定当前日志文件，filePattern指定归档格式 -->
        <RollingFile name="FILE_INFO" fileName="${LOG_PATH}/info.log" filePattern="${LOG_PATH}/info-%d{yyyy-MM-dd}.log">
            <!-- 阈值过滤器，只接受INFO及以上级别日志（此处与Logback的LevelFilter功能一致） -->
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 日志格式配置 -->
            <PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
            <!-- 滚动触发策略配置节点 -->
            <Policies>
                
                <!-- 时间触发策略，interval=1表示每天滚动一次，modulate=true调整时间（如按凌晨滚动） -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                
                <!-- 大小触发策略，当单个日志文件达到100MB时触发滚动 -->
                <SizeBasedTriggeringPolicy size="100MB"/>
            </Policies>
            
            <!-- 默认滚动策略，max=30表示最多保留30个归档文件 -->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>

        
        <!-- 错误日志滚动文件输出器，单独存储错误日志 -->
        <RollingFile name="FILE_ERROR" fileName="${LOG_PATH}/error.log" filePattern="${LOG_PATH}/error-%d{yyyy-MM-dd}.log">
            <!-- 只接受ERROR级别的日志 -->
            <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 日志格式配置 -->
            <PatternLayout pattern="${LOG_PATTERN}" charset="UTF-8"/>
            <!-- 滚动策略与普通日志一致，每天或100MB滚动一次 -->
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="100MB"/>
            </Policies>
            <!-- 保留30个归档错误日志文件 -->
            <DefaultRolloverStrategy max="30"/>
        </RollingFile>

        
        <!-- 异步输出器，将普通信息日志异步输出到FILE_INFO，提升性能 -->
        <Async name="ASYNC_INFO">
            <!-- 关联对应的同步输出器 -->
            <AppenderRef ref="FILE_INFO"/>
        </Async>
        <!-- 异步输出器，将错误日志异步输出到FILE_ERROR -->
        <Async name="ASYNC_ERROR">
            <AppenderRef ref="FILE_ERROR"/>
        </Async>
    </Appenders>

    
    <!-- 日志记录器（Loggers）配置节点，控制日志的输出规则 -->
    <Loggers>
        
        <!-- 开发环境（dev）配置，通过SpringProfile标签适配 -->
        <SpringProfile name="dev">
            <!-- 根日志器级别为INFO -->
            <Root level="INFO">
                <!-- 开发环境只输出到控制台 -->
                <AppenderRef ref="CONSOLE"/>
            </Root>
        </SpringProfile>

        <!-- 生产环境（prod）配置 -->
        <SpringProfile name="prod">
            <!-- 根日志器级别为INFO -->
            <Root level="INFO">
                <!-- 输出到控制台和异步文件输出器 -->
                <AppenderRef ref="CONSOLE"/>
                
                <AppenderRef ref="ASYNC_INFO"/>
                <AppenderRef ref="ASYNC_ERROR"/>
            </Root>
            
            <!-- 单独配置MyBatis Mapper的日志级别为DEBUG，便于查看SQL -->
            <Logger name="com.xxx.mapper" level="DEBUG" additivity="false">
                <!-- additivity="false"防止日志重复输出到根日志器 -->
                <AppenderRef ref="CONSOLE"/>
                <AppenderRef ref="ASYNC_INFO"/>
            </Logger>
        </SpringProfile>
    </Loggers>
</Configuration>
```

### 代码中使用Log4j2 ###

划重点：代码层面完全不需要修改！因为我们用的是SLF4J的门面API，只需要更换底层实现和配置文件，业务代码零侵入。直接复用上面Logback的测试代码即可。

四、Logback vs Log4j2-Spring 核心区别对比

很多同学纠结“选哪个”，其实核心看场景。下面从7个关键维度做对比，帮你快速决策：

|  对比维度   |  Logback  |  Log4j2-Spring  |
| :-----------: | :-----------: | :-----------: |
| Spring Boot集成度 | 默认集成，无需额外配置 | 依赖需排除Logback依赖，引入专用starter |
| 性能表现 | 性能一般，同步日志稳定，高并发下有瓶颈 | 性能优异，异步日志基于Disruptor，高并发下吞吐量提升明显 |
| 功能丰富度 | 满足基础需求，支持多环境、滚动日志等核心功能 | 功能更全面，支持异步、自定义插件、日志聚合等高级功能 |
| 配置复杂度 | 配置简单直观，学习成本低 | 配置稍复杂，尤其是异步和高级功能，学习成本较高 |
| 内存占用 | 内存占用中等 | 异步模式下内存占用略高，但可通过配置优化 |
| 社区活跃度 | 由SLF4J作者开发，社区稳定但更新频率较低 | Apache官方维护，更新频繁，bug修复及时 |
| 适用场景 | 中小项目、快速开发、对性能要求不高的场景 | 大型项目、高并发系统、对日志性能要求高的场景（如电商、支付） |

总结：小项目直接用Logback（省心），大项目高并发选Log4j2（性能强），二者切换成本极低，因为有SLF4J做门面。

## 五、常见问题排查 ##

### 配置文件不生效？ ###

- 检查配置文件名是否正确：Logback用`logback-spring.xml`，Log4j2用`log4j2-spring.xml`（带spring后缀才能支持多环境）；
- 检查配置文件路径是否在resources根目录下；
- Log4j2需确认是否排除了Logback依赖，避免依赖冲突。

### 异步日志没效果？ ###

- Log4j2需引入disruptor依赖；
- 检查配置文件中是否用了`<Async>`标签包裹文件`Appender`；
- 避免在日志中打印过大的对象（如集合），可能导致异步队列阻塞。

### 日志级别不生效？ ###

- 检查`additivity="false"`是否配置正确，避免子Logger日志重复输出；
- 确认`profile`环境是否激活（如启动参数`--spring.profiles.active=prod`）；
- 避免代码中手动修改日志级别，覆盖配置文件设置。

## 六、最后总结 ##

日志配置是Spring Boot开发的基础技能，今天我们从实战角度讲解了Logback和Log4j2-Spring的配置方法，又通过对比明确了二者的适用场景：

- 快速开发、中小项目：直接用默认的Logback，省心高效；
- 高并发、大型项目：切换到Log4j2+Disruptor异步日志，提升性能；
- 核心原则：用SLF4J门面API，解耦日志实现，方便后续切换。
