Spring Boot日志输出统一增加线程信息
引言
在Spring Boot应用中,日志输出是非常重要的。为了更好地追踪日志,我们通常会在日志中增加线程信息。本文将教会刚入行的开发者如何实现在Spring Boot中统一增加线程信息的日志输出。
整体流程
下表展示了实现此功能的整体流程:
步骤 | 描述 |
---|---|
1 | 导入相关依赖 |
2 | 创建自定义LoggerFilter |
3 | 创建自定义Logback配置 |
4 | 配置logback-spring.xml |
5 | 测试日志输出 |
接下来,我们将详细介绍每个步骤以及需要进行的操作。
步骤一:导入相关依赖
首先,我们需要在项目的pom.xml文件中导入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 导入logback依赖 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
步骤二:创建自定义LoggerFilter
创建一个自定义的LoggerFilter类,用于将线程信息添加到日志中。可以参考以下代码:
import org.slf4j.MDC;
import org.springframework.web.filter.AbstractRequestLoggingFilter;
import javax.servlet.http.HttpServletRequest;
public class ThreadInfoLoggerFilter extends AbstractRequestLoggingFilter {
@Override
protected void beforeRequest(HttpServletRequest request, String message) {
MDC.put("threadId", String.valueOf(Thread.currentThread().getId()));
}
@Override
protected void afterRequest(HttpServletRequest request, String message) {
MDC.remove("threadId");
}
}
上述代码中,我们继承了AbstractRequestLoggingFilter类,重写了beforeRequest和afterRequest方法。在beforeRequest方法中,我们将当前线程的ID放入了MDC(Mapped Diagnostic Context)中,这样在日志输出时就可以获取到线程信息。在afterRequest方法中,我们移除了MDC中的threadId。
步骤三:创建自定义Logback配置
接下来,我们需要创建一个自定义的Logback配置类,用于指定日志输出格式和使用自定义的LoggerFilter。可以参考以下代码:
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.status.InfoStatus;
import ch.qos.logback.core.status.StatusManager;
import ch.qos.logback.core.util.StatusPrinter;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import java.io.FileNotFoundException;
@Configuration
public class LogbackConfig implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 初始化LoggerContext
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.reset();
// 创建ConsoleAppender
ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
consoleAppender.setName("CONSOLE");
consoleAppender.setContext(loggerContext);
consoleAppender.setEncoder(createEncoder(loggerContext));
consoleAppender.start();
// 创建FileAppender
FileAppender<ILoggingEvent> fileAppender = new FileAppender<>();
fileAppender.setName("FILE");
fileAppender.setContext(loggerContext);
fileAppender.setEncoder(createEncoder(loggerContext));
fileAppender.setFile(ResourceUtils.getFile("classpath:logs/application.log").getPath());
fileAppender.start();
// 设置根Logger的Appender
ch.qos.logback.classic.Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.addAppender(consoleAppender);
rootLogger.addAppender(fileAppender);
rootLogger.setLevel(Level.INFO);
// 打印Logback的内部状态
StatusManager statusManager = loggerContext.getStatusManager();
if