如何在Java Spring Boot API请求中添加UUID格式的Correlation-Id头部
在Spring Boot(Swagger生成代码)中自动添加Correlation-Id请求头并关联日志
1. 用ThreadLocal实现Correlation-Id上下文共享
先写一个工具类,用ThreadLocal存储Correlation-Id,保证请求链路内的线程安全,同时集成你已有的UUID生成逻辑:
public class CorrelationIdHolder { private static final ThreadLocal<String> CORRELATION_ID = new ThreadLocal<>(); public static String getCorrelationId() { String id = CORRELATION_ID.get(); if (id == null) { id = generateUniqueCorrelationId(); setCorrelationId(id); } return id; } public static void setCorrelationId(String correlationId) { CORRELATION_ID.set(correlationId); } public static void clear() { CORRELATION_ID.remove(); } private static String generateUniqueCorrelationId() { return UUID.randomUUID().toString(); } }
2. 编写拦截器自动注入/处理请求头
实现Spring的HandlerInterceptor,在请求进入时自动生成(或复用传入的)Correlation-Id,同时写入响应头方便客户端追踪,请求结束后清理上下文:
@Component public class CorrelationIdInterceptor implements HandlerInterceptor { private static final String CORRELATION_ID_HEADER = "Correlation-Id"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 优先取请求头里的ID,没有则自动生成 String correlationId = request.getHeader(CORRELATION_ID_HEADER); if (correlationId == null || correlationId.isBlank()) { correlationId = CorrelationIdHolder.generateUniqueCorrelationId(); } CorrelationIdHolder.setCorrelationId(correlationId); // 把ID写入响应头,让客户端能拿到 response.setHeader(CORRELATION_ID_HEADER, correlationId); // 放入MDC供日志使用 MDC.put("correlationId", correlationId); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 必须清理,避免线程复用导致ID混乱或内存泄漏 CorrelationIdHolder.clear(); MDC.remove("correlationId"); } }
然后注册这个拦截器,让它对所有API生效:
@Configuration public class WebConfig implements WebMvcConfigurer { private final CorrelationIdInterceptor correlationIdInterceptor; public WebConfig(CorrelationIdInterceptor correlationIdInterceptor) { this.correlationIdInterceptor = correlationIdInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(correlationIdInterceptor) .addPathPatterns("/**"); } }
3. 让Swagger生成的API自动关联Correlation-Id
在你的Swagger YAML中定义全局请求参数,这样生成的接口文档会包含该字段,Swagger UI调用时也会自动提示(或携带默认UUID):
openapi: 3.0.3 info: title: 你的API名称 version: 1.0.0 servers: - url: http://localhost:8080 components: parameters: CorrelationId: name: Correlation-Id in: header required: false # 设为非必填,拦截器会自动兜底生成 schema: type: string format: uuid example: "550e8400-e29b-41d4-a716-446655440000" # 所有接口引用这个全局参数 paths: /your-api-path: get: parameters: - $ref: '#/components/parameters/CorrelationId' responses: '200': description: 成功响应
如果需要所有接口自动关联,也可以通过OpenAPI Generator的配置参数(比如globalParameters)批量添加,不需要逐个接口写引用。
4. 日志中自动带上Correlation-Id
如果你用SLF4J + Logback,修改日志配置文件(比如logback-spring.xml),在格式中加入%X{correlationId}:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %X{correlationId} - %msg%n</pattern> </encoder> </appender>
这样所有日志都会自动带上当前请求的Correlation-Id,方便排查问题时追踪完整链路。
额外提示
- 如果你的服务需要调用其他微服务,可以给Feign添加
RequestInterceptor,把Correlation-Id传递过去,实现全链路追踪。 - 务必保证
ThreadLocal和MDC在请求结束后清理,否则会出现线程复用导致的ID错乱或内存泄漏问题。
内容的提问来源于stack exchange,提问作者Ravi
相关产品推荐
相关产品推荐

