微服务中怎么获取请求头信息-何时使用? 当需要访问 @RequestHeader 不直接支持的功能,或者需要更底层的控制时(虽然比较少见)。 3. 在过滤器 (Filter) 或拦截器 (Interceptor) 中获取 在微服务中,很多横切关注点(Cross-Cutting Concerns)如认证、授权、日志记录、分布式追踪上下文传播等,在请求到达 Controller 之前处理。这时,可以在 Filter 或 Interceptor 中获取请求头。 示例 (使用 Servlet Filter):

时间:2025-05-06 07:05:05
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC; // 用于日志上下文
import org.springframework.stereotype.Component;
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;

@Component // 让 Spring 管理这个 Filter
public class LoggingAndTraceFilter extends OncePerRequestFilter {

    private static final Logger log = LoggerFactory.getLogger(LoggingAndTraceFilter.class);
    private static final String TRACE_ID_HEADER = "X-Trace-ID";
    private static final String TENANT_ID_HEADER = "X-Tenant-ID";
    private static final String TRACE_ID_MDC_KEY = "traceId";
    private static final String TENANT_ID_MDC_KEY = "tenantId";


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // 1. 从请求头获取或生成 Trace ID
        String traceId = request.getHeader(TRACE_ID_HEADER);
        if (traceId == null || traceId.isEmpty()) {
            traceId = UUID.randomUUID().toString();
            log.debug("Generated new Trace ID: {}", traceId);
            // 如果需要传播,可将生成的 ID 添加到响应头或下游请求头
        }

        // 2. 从请求头获取 Tenant ID
        String tenantId = request.getHeader(TENANT_ID_HEADER);
        if (tenantId == null) {
            tenantId = "unknown"; // Or handle as an error depending on requirements
        }

        // 3. 将信息放入 MDC (Mapped Diagnostic Context) 以便日志自动包含这些信息
        MDC.put(TRACE_ID_MDC_KEY, traceId);
        MDC.put(TENANT_ID_MDC_KEY, tenantId);

        log.info("Request received: {} {} for Tenant: {}", request.getMethod(), request.getRequestURI(), tenantId);

        try {
            // 继续处理请求链 (最终会到达 Controller)
            filterChain.doFilter(request, response);
        } finally {
            // 4. 请求处理完毕后,清理 MDC,避免影响线程池中的下一个请求
            MDC.remove(TRACE_ID_MDC_KEY);
            MDC.remove(TENANT_ID_MDC_KEY);
            log.info("Request completed: {} {}", request.getMethod(), request.getRequestURI());
        }
    }
}