SpringBoot项目如何使用Log4j2+SLF4J构建日志

目录

1、添加项目依赖

2、创建TraceId过滤器

3、配置Log4j2以输出TraceId

4、在代码中记录日志

5、日志挂载位置

[5.1 通过应用配置文件设置](#5.1 通过应用配置文件设置)

[5.2 通过自定义日志配置文件设置](#5.2 通过自定义日志配置文件设置)

[5.3 通过命令行或环境变量设置](#5.3 通过命令行或环境变量设置)


1、添加项目依赖

确保的pom.xml中包含Spring Boot Starter Log4j2的依赖,同时排除默认的Logback

XML 复制代码
<dependencies>
    <!-- Spring Boot Log4j2 Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <!-- 排除掉默认的 logback 依赖 -->
            <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>
</dependencies>

2、创建TraceId过滤器

这个Filter负责在请求开始时生成TraceId并放入上下文,在请求结束后清理

java 复制代码
import org.apache.logging.log4j.ThreadContext;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

@Component
public class TraceIdFilter implements Filter {
    
    // 你可以自定义请求头中TraceId的名字
    private static final String TRACE_ID_HEADER = "X-Trace-Id";
    // 这是TraceId在Log4j2 ThreadContext中存储的key
    private static final String TRACE_ID_KEY = "traceId";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 尝试从请求头中获取TraceId,如果没有则生成一个
        String traceId = httpRequest.getHeader(TRACE_ID_HEADER);
        if (traceId == null || traceId.isEmpty()) {
            // 生成唯一ID,这里使用UUID,你可以根据需要调整
            traceId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
        }

        // 将TraceId放入Log4j2的ThreadContext,这样日志就能自动打印了
        ThreadContext.put(TRACE_ID_KEY, traceId);
        // 可选:将TraceId设置到响应头,方便前端或下游服务追踪
        httpResponse.setHeader(TRACE_ID_HEADER, traceId);

        try {
            chain.doFilter(request, response); // 继续执行请求链
        } finally {
            // 请求处理完毕,务必清理ThreadContext,避免内存泄漏和数据污染
            ThreadContext.remove(TRACE_ID_KEY);
        }
    }
}

3、配置Log4j2以输出TraceId

修改src/main/resources/log4j2.xml配置文件,在日志输出模式(Pattern)中加入TraceId

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <!-- 控制台输出配置 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 设置日志输出格式 -->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{traceId}] %logger{36} - %msg%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
        </Root>
    </Loggers>
</Configuration>

关键说明

  • 格式中的%X{traceId}就是一个占位符,它会自动从Log4j2的ThreadContext中读取key为"traceId"的值 。如果不存在,则该处输出为空。

4、在代码中记录日志

现在可以在代码中正常使用SLF4J记录日志,TraceId会自动出现在日志中。

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 DemoController {
    
    private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
    
    @GetMapping("/test")
    public String testEndpoint() {
        logger.info("收到请求"); // 日志会自动包含traceId
        // ... 你的业务逻辑
        return "请求完成";
    }
}

5、日志挂载位置

在Spring Boot项目中,设置日志的挂载位置主要有两种思路:一种是通过应用的配置文件(如application.propertiesapplication.yml)进行快速设置,另一种是通过自定义的日志配置文件(如logback-spring.xmllog4j2-spring.xml)实现更精细的控制。

配置方式 核心参数 作用 示例
配置文件 (application.properties/yml) logging.file.name 设置完整的日志文件路径和文件名 logging.file.name=/var/log/myapp/app.log
logging.file.path 设置日志文件的目录 ,Spring Boot会自动在该目录下生成名为spring.log的文件。 logging.file.path=/var/log/myapp
logging.config 指定自定义日志配置文件的位置。 logging.config=classpath:logback-spring.xml
自定义配置 (logback-spring.xml) LOG_FILELOG_PATH 在XML配置文件中,使用Spring Boot预定义的系统属性来动态引用在application.properties中设置的日志路径或文件。 <file>${LOG_FILE}</file>

5.1 通过应用配置文件设置

这是最简单直接的方法,适合大多数常规需求。

指定完整路径和文件名:

使用 logging.file.name 可以精确控制日志文件的存储位置和名称。

bash 复制代码
# application.properties 示例
logging.file.name=/var/log/your-app/application.log
bash 复制代码
# application.yml 示例
logging:
  file:
    name: /var/log/your-app/application.log

仅指定目录:

使用 logging.file.path,Spring Boot会在该目录下创建固定的spring.log文件。

bash 复制代码
# application.properties 示例
logging.file.path=/var/log/your-app

5.2 通过自定义日志配置文件设置

当有复杂需求时(如按天归档、按文件大小分割、对不同级别日志进行过滤等),建议使用自定义日志配置文件。

创建配置文件:src/main/resources 目录下创建 logback-spring.xml(如果使用Logback)或 log4j2-spring.xml(如果使用Log4j2)。

在配置文件中引用外部路径: 在XML配置中,可以使用 ${LOG_FILE}${LOG_PATH} 来获取在 application.properties 中设置的值,这使得配置非常灵活。

XML 复制代码
<!-- logback-spring.xml 示例片段 -->
<configuration>
    <springProperty scope="context" name="LOG_HOME" source="logging.file.path" defaultValue="/tmp/logs"/>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 使用在application.properties中设置的logging.file.path -->
        <file>${LOG_HOME}/spring.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 按天归档日志 -->
            <fileNamePattern>${LOG_HOME}/application.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 保留最多30天的日志历史 -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 其他配置... -->
</configuration>

5.3 通过命令行或环境变量设置

在部署时(例如在Kubernetes或Docker容器中),通过命令行参数或环境变量来覆盖配置文件中的设置,这种方式非常有用。

命令行参数:

bash 复制代码
java -jar your-app.jar --logging.file.name=/path/to/your/logfile.log

环境变量:

bash 复制代码
export LOGGING_FILE_NAME=/path/to/your/logfile.log
java -jar your-app.jar

注意事项:

  • 挂载到容器外部 :在Docker或Kubernetes中部署时,务必 通过卷挂载(Volume)的方式将配置的日志目录(如/var/log/your-app)挂载到宿主机上。这样可以避免容器重启后日志丢失,也方便日志收集和管理。

  • 权限问题 :确保你的应用有在指定日志目录下写入文件的权限,这是一个常见的部署问题。

  • 路径选择 :生产环境中,日志通常放在 /var/log/ 目录下,并根据应用名称建立子目录,例如 /var/log/your-app-name/

  • 配置优先级 :如果同时设置了 logging.file.namelogging.file.pathlogging.file.name 的优先级更高

相关推荐
多多*2 小时前
牛客周赛 Round 117 ABCDE 题解
java·开发语言·数据结构·算法·log4j·maven
WZTTMoon2 小时前
从 “完整对象” 视角看Spring 循环依赖
java·spring boot·后端·spring
baviya2 小时前
一文彻底搞懂 Maven 依赖——从 <dependency> 到依赖冲突,带你看懂 Maven 的“江湖规矩”
java·maven
一瓢一瓢的饮 alanchan2 小时前
Flink原理与实战(java版)#第1章 Flink快速入门(第一节IDE词频统计)
java·大数据·flink·kafka·实时计算·离线计算·流批一体化计算
java_logo2 小时前
Docker 容器化部署 QINGLONG 面板指南
java·运维·docker·容器·eureka·centos·rabbitmq
那我掉的头发算什么2 小时前
【javaEE】多线程--认识线程、多线程
java·jvm·redis·性能优化·java-ee·intellij-idea
Pluchon2 小时前
硅基计划6.0 JavaEE 叁 文件IO
java·学习·java-ee·文件操作·io流
程序员卷卷狗2 小时前
联合索引的最左前缀原则与失效场景
java·开发语言·数据库·mysql
纪莫2 小时前
技术面:SpringCloud(SpringCloud有哪些组件,SpringCloud与Dubbo的区别)
java·spring·java面试⑧股