You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot微服务配置后请求UUID未生成问题排查求助

Spring Boot 微服务请求唯一UUID未生成问题解决方案

核心问题排查&修改点

  • 问题1:Filter未配置拦截路径,重复实例化冲突
    当前的FilterRegistrationBean未指定拦截的URL模式,不会默认拦截所有请求;同时Slf4jMDCFilter加了@Component注解,又在配置类中手动实例化注册,导致重复Bean冲突,Filter无法正常生效。
    修复方式:
    1. 移除Slf4jMDCFilter类上的@Component注解
    2. 在Filter注册逻辑中添加registrationBean.addUrlPatterns("/*")指定拦截所有请求
    3. 移除配置类上冗余的@Component注解(@Configuration本身已包含组件扫描能力)
    4. 补充配置类的getter/setter方法,保障@ConfigurationProperties注入能力
  • 问题2:日志格式未配置MDC变量输出
    当前的application.properties仅配置了日志滚动策略,未在日志输出模板中指定要打印MDC中存储的UUID值,即使UUID生成成功也不会在日志中显示。
    修复方式:新增日志格式配置,通过%X{Slf4jMDCFilter.UUID}引入MDC存储的UUID值。
  • 问题3:Filter缺少构造函数
    手动实例化Filter时需要对应参数的构造函数,否则参数无法传入。

修改后完整代码

1. Slf4jMDCFilterConfiguration.java

package first.app.microservice.uuid;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "config.slf4filter")
public class Slf4jMDCFilterConfiguration {

    public static final String DEFAULT_RESPONSE_TOKEN_HEADER = "Response_Token";
    public static final String DEFAULT_MDC_UUID_TOKEN_KEY = "Slf4jMDCFilter.UUID";

    private String responseHeader = DEFAULT_RESPONSE_TOKEN_HEADER;
    private String mdcTokenKey = DEFAULT_MDC_UUID_TOKEN_KEY;
    private String requestHeader = null;

    @Bean
    public FilterRegistrationBean servletRegistrationBean() {
        final FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        final Slf4jMDCFilter log4jMDCFilterFilter = new Slf4jMDCFilter(responseHeader, mdcTokenKey, requestHeader);
        registrationBean.setFilter(log4jMDCFilterFilter);
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(2);
        return registrationBean;
    }

    public String getResponseHeader() {
        return responseHeader;
    }

    public void setResponseHeader(String responseHeader) {
        this.responseHeader = responseHeader;
    }

    public String getMdcTokenKey() {
        return mdcTokenKey;
    }

    public void setMdcTokenKey(String mdcTokenKey) {
        this.mdcTokenKey = mdcTokenKey;
    }

    public String getRequestHeader() {
        return requestHeader;
    }

    public void setRequestHeader(String requestHeader) {
        this.requestHeader = requestHeader;
    }
}

2. Slf4jMDCFilter.java

package first.app.microservice.uuid;

import lombok.Data;
import lombok.EqualsAndHashCode;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

@Data
@EqualsAndHashCode(callSuper = false)
public class Slf4jMDCFilter extends OncePerRequestFilter {

    private final String responseHeader;
    private final String mdcTokenKey;
    private final String requestHeader;

    public Slf4jMDCFilter(String responseHeader, String mdcTokenKey, String requestHeader) {
        this.responseHeader = responseHeader;
        this.mdcTokenKey = mdcTokenKey;
        this.requestHeader = requestHeader;
    }

    @Override
    protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain)
            throws IOException, ServletException {
        try {
            final String token;
            if (!StringUtils.isEmpty(requestHeader) && !StringUtils.isEmpty(request.getHeader(requestHeader))) {
                token = request.getHeader(requestHeader);
            } else {
                token = UUID.randomUUID().toString().toUpperCase().replace("-", "");
            }
            MDC.put(mdcTokenKey, token);
            if (!StringUtils.isEmpty(responseHeader)) {
                response.addHeader(responseHeader, token);
            }
            chain.doFilter(request, response);
        } finally {
            MDC.remove(mdcTokenKey);
        }
    }
}

3. application.properties 新增配置

# 原有配置保持不变,新增以下两行日志格式配置
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{Slf4jMDCFilter.UUID}] [%thread] %-5level %logger{36} - %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{Slf4jMDCFilter.UUID}] [%thread] %-5level %logger{36} - %msg%n

验证方式

修改完成后重启服务,调用任意接口,查看接口返回的响应头中是否存在Response_Token字段,且日志中[]内已打印32位大写UUID即可。

内容的提问来源于stack exchange,提问作者Pouya Najafi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 04:57:04