Spring Boot微服务配置后请求UUID未生成问题排查求助
Spring Boot 微服务请求唯一UUID未生成问题解决方案
核心问题排查&修改点
- 问题1:Filter未配置拦截路径,重复实例化冲突
当前的FilterRegistrationBean未指定拦截的URL模式,不会默认拦截所有请求;同时Slf4jMDCFilter加了@Component注解,又在配置类中手动实例化注册,导致重复Bean冲突,Filter无法正常生效。
修复方式:- 移除
Slf4jMDCFilter类上的@Component注解 - 在Filter注册逻辑中添加
registrationBean.addUrlPatterns("/*")指定拦截所有请求 - 移除配置类上冗余的
@Component注解(@Configuration本身已包含组件扫描能力) - 补充配置类的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
相关产品推荐
相关产品推荐

