java中实现日志自动打印traceid的核心是slf4j mdc结合sleuth(boot 3.x前)或micrometer tracing(boot 3.x+),二者均自动注入mdc并支持logback配置%x{traceid:-}输出,纯手工方式需filter+uuid+mdc.put/clear。

在 Java 中实现日志中自动打印请求追踪 ID(TraceId),核心是利用 SLF4J MDC(Mapped Diagnostic Context) 结合分布式追踪框架(如 Spring Cloud Sleuth 或 Micrometer Tracing)来透传和注入 TraceId。
使用 Spring Cloud Sleuth(推荐,Spring Boot 3.x 前)
Sleuth 会自动为每个 HTTP 请求生成唯一 TraceId(和 SpanId),并将其注入 MDC,只要日志框架(如 Logback)配置了对应占位符,就能直接输出。
- 添加依赖(Maven):
- 确保日志配置(如 logback-spring.xml)中包含
%X{traceId}或%X{traceId:-}(后者避免空值时报错):
- 无需手动设置 —— Sleuth 在 Filter 中自动完成 MDC 的 put 和 clear,线程结束后自动清理,防止日志污染。
使用 Micrometer Tracing(Spring Boot 3.x+ 官方推荐)
Spring Boot 3 起,Sleuth 已被 Micrometer Tracing 取代。它同样支持自动 MDC 注入,但需启用配置:
- 添加依赖:
- 在
application.yml中启用 MDC:
tracing:
otel:
propagation:
type: b3
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - [%X{traceId:-},%X{spanId:-}] %msg%n"
- Micrometer 默认开启 MDC 自动绑定(
tracing.baggage.remote-fields=traceId,spanId非必需,默认已支持)。
纯手工方式(无框架或需自定义场景)
若不使用 Sleuth/Micrometer,可基于 javax.servlet.Filter + MDC 手动注入 TraceId:
- 生成 TraceId(例如用 UUID):
- 在 Filter 中写入 MDC,并在 finally 中清除:
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
String traceId = UUID.randomUUID().toString().replace("-", "");
MDC.put("traceId", traceId);
try {
chain.doFilter(req, res);
} finally {
MDC.clear();
}
}
}
- 注意:跨线程时需手动传递(如用
ThreadLocal+Runnable包装,或使用MDC.getCopyOfContextMap()透传)。
验证与调试技巧
快速确认 TraceId 是否生效:
- 启动应用后发一个 HTTP 请求(如
curl http://localhost:8080/api/test); - 查看控制台日志,确认每行开头或指定位置出现类似
[a1b2c3d4e5f67890,1234567890abcdef]的字段; - 在 Controller 中临时打印:
log.info("TraceId in controller: {}", MDC.get("traceId")); - 若为空,检查 Filter 是否注册、MDC 是否被提前 clear、是否用了线程池未传递上下文(如
CompletableFuture需配合ThreadPoolTaskExecutor+new LoggingTaskDecorator())。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











