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

Spring WebFlux中ThreadLocal实现及跨微服务Header传递咨询

Spring WebFlux 跨微服务Header自动传递实现方案

首先要明确:Spring WebFlux 是响应式编程模型,ThreadLocal并不适用——因为响应式流会在线程池之间切换,ThreadLocal的上下文会丢失。正确的做法是使用Reactor提供的Context来存储和传递Header信息。

实现步骤

1. 定义Header常量和上下文Key

先统一要传递的Header名称,比如X-Request-Id,同时定义Reactor Context的Key:

public class HeaderConstants {
    public static final String REQUEST_ID_HEADER = "X-Request-Id";
    public static final ContextKey<String> REQUEST_ID_CONTEXT_KEY = ContextKey.create("requestId");
}

2. 编写WebFilter拦截入站请求,将Header存入Reactor Context

这个Filter会在每个请求进来时,提取指定Header,存入当前Reactor的Context中:

@Component
public class RequestIdFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String requestId = exchange.getRequest().getHeaders().getFirst(HeaderConstants.REQUEST_ID_HEADER);
        // 如果Header不存在,生成一个默认值(可选)
        if (requestId == null) {
            requestId = UUID.randomUUID().toString();
        }
        // 将requestId存入Reactor Context
        return chain.filter(exchange)
                .contextWrite(context -> context.put(HeaderConstants.REQUEST_ID_CONTEXT_KEY, requestId));
    }
}

3. 自定义WebClient过滤器,从Context中获取Header并添加到出站请求

编写一个ExchangeFilterFunction,在WebClient发送请求前,从当前Reactor Context中取出Header,添加到请求头里:

@Component
public class RequestIdExchangeFilter {
    public ExchangeFilterFunction addRequestIdHeader() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            // 从Context中获取requestId
            return Mono.deferContextual(contextView -> {
                String requestId = contextView.getOrDefault(HeaderConstants.REQUEST_ID_CONTEXT_KEY, "");
                if (!requestId.isEmpty()) {
                    // 构建新的请求,添加Header
                    ClientRequest modifiedRequest = ClientRequest.from(clientRequest)
                            .header(HeaderConstants.REQUEST_ID_HEADER, requestId)
                            .build();
                    return Mono.just(modifiedRequest);
                }
                return Mono.just(clientRequest);
            });
        });
    }
}

4. 配置WebClient,注入自定义过滤器

创建WebClient Bean时,把上面的过滤器添加进去,这样所有通过这个WebClient发送的请求都会自动携带Header:

@Configuration
public class WebClientConfig {
    @Autowired
    private RequestIdExchangeFilter requestIdExchangeFilter;

    @Bean
    public WebClient webClient() {
        return WebClient.builder()
                .filter(requestIdExchangeFilter.addRequestIdHeader())
                .build();
    }
}

5. 业务中使用WebClient调用其他微服务

在Service层注入WebClient直接使用即可,无需手动处理Header:

@Service
public class DemoService {
    @Autowired
    private WebClient webClient;

    public Mono<String> callOtherService() {
        return webClient.get()
                .uri("http://other-service/api/demo")
                .retrieve()
                .bodyToMono(String.class);
    }
}

关键说明

  • 为什么不用ThreadLocal?:Reactor的线程模型是异步非阻塞的,一个请求的处理会在多个线程间切换,ThreadLocal的上下文无法跨线程传递,会导致Header丢失。
  • Reactor Context的作用:Context是绑定在Mono/Flux流上的,会跟随流的整个生命周期,无论线程如何切换,都能正确获取到存储的信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 06:01:35