首页 / Spring Boot 入门教程 / 日志体系

Spring Boot 入门教程

日志体系

本教程共 48 篇 · 第 14 篇 · 更新于 2026-08-13 · 约 4 分钟阅读

日志Logbacklog4j2SLF4J日志级别日志格式logback-spring.xml

本节目标:搞懂 Spring Boot 的日志默认配置,学会调级别、写文件、自定义格式,还能换成 log4j2。

默认日志框架

Spring Boot 内部用 Commons Logging 做抽象,具体实现默认是 Logback。

用 Starter 启动的项目,Logback 已经就位,一行配置都不用写。

它还能把 JUL、Log4J、SLF4J 的日志都路由过来,统一输出。

代码里写日志,用的是 SLF4J 门面 API。门面像插座转换头:不管背后是哪个日志框架,你只插一个口。换底层框架不用改代码。

默认日志格式

启动时能看到类似这样的输出:

2026-06-10T16:33:40.717Z  INFO 53358 --- [hello-app] [           main] o.s.boot.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'

从左到右各段含义:

  • 日期时间,毫秒精度。
  • 日志级别。
  • 进程 ID。
  • --- 分隔符。
  • 应用名,来自 spring.application.name
  • 线程名。
  • 日志器名,通常是类名缩写。
  • 日志内容。

级别顺序:TRACE < DEBUG < INFO < WARN < ERROR。

Note

Logback 没有 FATAL 级别,FATAL 会映射成 ERROR。

在代码里打日志

SLF4J 的标准姿势:

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 HelloController {

    private static final Logger log = LoggerFactory.getLogger(HelloController.class);

    @GetMapping("/hello")
    public String hello(String name) {
        log.info("收到请求,参数 name={}", name);
        log.debug("这里只有调试时才输出");
        return "hello " + name;
    }
}

{} 是占位符,参数会自动拼进去。别用字符串拼接,性能差一截。

调整日志级别

配置文件里用 logging.level. 前缀:

logging:
  level:
    root: info
    org.springframework.web: debug
    com.example.demo: warn

root 是全局兜底级别。包名越具体,优先级越高。

也可以单独调某个类:

logging:
  level:
    com.example.demo.HelloController: trace

环境变量也能调,包级生效:

LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG
Tip

线上排查问题,临时调高某个包的级别,不用改代码重新发版。改配置重启即可。

快速调试模式

不想一个个配级别?启动时加 --debug

java -jar hello-app.jar --debug

这会把核心框架(容器、Spring Boot 自身)的日志调到 DEBUG,顺带打印的条件报告见 §6。

--trace 更狠,连 Hibernate 的 SQL 生成都输出。

配置文件里写 debug: true 效果一样。

输出到文件

默认只打控制台,不打文件。想落盘,配置两个键:

logging:
  file:
    name: logs/myapp.log

或者只给目录,文件名固定为 spring.log:

logging:
  file:
    path: /var/log/myapp

两个都写时,file.name 生效,file.path 被忽略。

文件默认 10MB 滚动一次。滚动策略可以调:

logging:
  logback:
    rollingpolicy:
      max-file-size: 20MB
      max-history: 14
      total-size-cap: 1GB
  • max-file-size:单文件多大开始滚动。
  • max-history:保留多少个归档文件。
  • total-size-cap:归档总大小上限。

自定义日志格式

不想用默认格式?改 pattern:

logging:
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n"

%d 时间、%level 级别、%thread 线程、%logger 日志器名、%msg 消息、%n 换行。

支持 ANSI 颜色,比如让级别按颜色显示:

logging:
  pattern:
    console: "%clr(%5p) %clr([%thread]){yellow} %clr(%logger{36}){cyan} - %msg%n"

日志分组

想把一组相关包一起调级别?先定义分组:

logging:
  group:
    tomcat: org.apache.catalina,org.apache.coyote,org.apache.tomcat

然后一条命令调整个组:

logging:
  level:
    tomcat: trace

内置分组直接用:web 涵盖 Spring Web 全家,sql 涵盖 JDBC 和 Hibernate SQL。

完整自定义:logback-spring.xml

配置文件的键不够用时,用 Logback 自己的 XML。放 src/main/resources/logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/myapp.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/myapp-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>

    <logger name="com.example.demo" level="DEBUG"/>
</configuration>
Note

文件名要用 logback-spring.xml,别用 logback.xml。带 -spring 的变体能被 Spring Boot 完全接管,支持 profile 等扩展。

切换到 log4j2

换框架只要动依赖。先排除默认的 Logback:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webmvc</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

再放一个 src/main/resources/log4j2-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <RollingFile name="RollingFile"
                     fileName="logs/myapp.log"
                     filePattern="logs/myapp-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="10MB"/>
            </Policies>
            <DefaultRollOverStrategy max="7"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>
</Configuration>

代码不用改。SLF4J 门面把差异挡住了。

Tip

只有特殊团队要求(如现有日志采集体系基于 log4j2)才值得切换。默认 Logback 对绝大多数项目够用。

结构化日志(JSON)

日志要送给日志平台(ELK、Loki 等)时,JSON 格式比文本好解析。

Spring Boot 内置支持三种 JSON 格式:

  • ecs:Elastic Common Schema。
  • gelf:Graylog 格式。
  • logstash:Logstash 格式。

开启方式一行配置:

logging:
  structured:
    format:
      console: ecs
      file: ecs

输出会变成 JSON 行:

{"@timestamp":"2026-08-13T10:00:00.000Z","log.level":"INFO","message":"Tomcat started on port 8080","service.name":"hello-app"}

采集端按字段过滤、聚合都很方便。

MDC 上下文信息

想给每行日志带上请求 ID、用户 ID?用 MDC。

MDC 是日志框架的上下文存储,ThreadLocal 实现,同线程内共享:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    private static final Logger log = LoggerFactory.getLogger(HelloController.class);

    @GetMapping("/hello")
    public String hello(String userId) {
        MDC.put("userId", userId);
        try {
            log.info("处理用户请求");
            return "hello";
        } finally {
            MDC.remove("userId");
        }
    }
}

配合 logging.pattern.level 把 MDC 值打出来:

logging:
  pattern:
    level: "user:%X{userId} %5p"
Warning

MDC 用完必须清理。不 remove 的话,线程池复用时旧值会串到下一个请求。

日志性能习惯

日志写得多,性能就掉得快。三个习惯值得养成:

  • 参数用 {} 占位符,别用字符串拼接。
  • DEBUG 日志包一层级别判断,参数构造开销大时尤其重要。
if (log.isDebugEnabled()) {
    log.debug("用户列表: {}", expensiveToString());
}
  • 高频路径只打 INFO 及以下,别什么都 DEBUG。

生产环境默认 INFO,打不进文件的就是没发生。

小结

  • 默认 Logback + SLF4J,开箱即用。
  • logging.level. 调级别,--debug 快速调试。
  • logging.file.name 落盘,默认 10MB 滚动。
  • logging.pattern.* 自定义格式。
  • 复杂需求用 logback-spring.xml
  • 结构化日志一行配置输出 JSON,MDC 携带上下文。
  • 换 log4j2 只需改依赖和配置文件。