SpringBoot项目如何使用Log4j2+SLF4J构建日志
目录
1、添加项目依赖
2、创建TraceId过滤器
3、配置Log4j2以输出TraceId
4、在代码中记录日志
5、日志挂载位置
5.1 通过应用配置文件设置
5.2 通过自定义日志配置文件设置
5.3 通过命令行或环境变量设置
1、添加项目依赖
确保的pom.xml中包含Spring Boot Starter Log4j2的依赖,同时排除默认的Logback
<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并放入上下文,在请求结束后清理
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中存储的keyprivate static final String TRACE_ID_KEY = "traceId";@Overridepublic 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 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会自动出现在日志中。
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.properties或application.yml)进行快速设置,另一种是通过自定义的日志配置文件(如logback-spring.xml或log4j2-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_FILE 或 LOG_PATH | 在XML配置文件中,使用Spring Boot预定义的系统属性来动态引用在application.properties中设置的日志路径或文件。 | <file>${LOG_FILE}</file> |
5.1 通过应用配置文件设置
这是最简单直接的方法,适合大多数常规需求。
指定完整路径和文件名:
使用 logging.file.name 可以精确控制日志文件的存储位置和名称。
# application.properties 示例
logging.file.name=/var/log/your-app/application.log
# application.yml 示例
logging:file:name: /var/log/your-app/application.log
仅指定目录:
使用 logging.file.path,Spring Boot会在该目录下创建固定的spring.log文件。
# 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 中设置的值,这使得配置非常灵活。
<!-- 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容器中),通过命令行参数或环境变量来覆盖配置文件中的设置,这种方式非常有用。
命令行参数:
java -jar your-app.jar --logging.file.name=/path/to/your/logfile.log
环境变量:
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.name和logging.file.path,logging.file.name的优先级更高。
