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

Spring Boot 3中WebClient或HTTP接口是否存在Feign.RequestInterceptor等价接口?

Spring Boot 3 中 WebClient/HTTP 接口的请求拦截方案(等价于 Feign.RequestInterceptor)

在Spring Boot 3环境下,WebClient和RestTemplate(对应传统同步HTTP接口场景)都提供了与Feign.RequestInterceptor功能等价的拦截机制,以下是具体实现方案:

一、WebClient 对应拦截方案:ExchangeFilterFunction

WebClient使用ExchangeFilterFunction作为请求拦截器,可在请求发送前修改请求实例,完全覆盖Feign.RequestInterceptor的功能。对应你提供的Feign拦截器逻辑,实现示例如下:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import reactor.core.publisher.Mono;

import java.util.UUID;

public class TokenWebClientFilter implements ExchangeFilterFunction {

    private static final Logger LOG = LoggerFactory.getLogger(TokenWebClientFilter.class);
    public static final String TOKEN_HEADER_NAME = "my-token";

    @Override
    public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
        String traceToken = computeTraceTokenIfAbsent();
        // 修改请求,添加token头
        ClientRequest modifiedRequest = ClientRequest.from(request)
                .header(TOKEN_HEADER_NAME, traceToken)
                .build();
        return next.exchange(modifiedRequest);
    }

    private String computeTraceTokenIfAbsent() {
        try {
            var attribute = RequestContextHolder.currentRequestAttributes()
                    .getAttribute(TOKEN_HEADER_NAME, RequestAttributes.SCOPE_REQUEST);
            if (attribute instanceof String strAttribute) {
                RequestContextHolder.currentRequestAttributes()
                        .setAttribute(TOKEN_HEADER_NAME, strAttribute, RequestAttributes.SCOPE_REQUEST);
                return strAttribute;
            }
        } catch (IllegalStateException e) {
            LOG.debug("Not in a request context: Creating new token for outgoing request.", e);
        }
        return UUID.randomUUID().toString();
    }
}

配置WebClient时注册该过滤器:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient(TokenWebClientFilter tokenFilter) {
        return WebClient.builder()
                .filter(tokenFilter)
                .build();
    }

    @Bean
    public TokenWebClientFilter tokenWebClientFilter() {
        return new TokenWebClientFilter();
    }
}

二、RestTemplate 对应拦截方案:ClientHttpRequestInterceptor

如果使用传统同步HTTP客户端RestTemplate,可通过ClientHttpRequestInterceptor实现请求拦截,功能与Feign.RequestInterceptor一致。实现示例如下:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.io.IOException;
import java.util.UUID;

public class TokenRestTemplateInterceptor implements ClientHttpRequestInterceptor {

    private static final Logger LOG = LoggerFactory.getLogger(TokenRestTemplateInterceptor.class);
    public static final String TOKEN_HEADER_NAME = "my-token";

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        String traceToken = computeTraceTokenIfAbsent();
        request.getHeaders().add(TOKEN_HEADER_NAME, traceToken);
        return execution.execute(request, body);
    }

    private String computeTraceTokenIfAbsent() {
        try {
            var attribute = RequestContextHolder.currentRequestAttributes()
                    .getAttribute(TOKEN_HEADER_NAME, RequestAttributes.SCOPE_REQUEST);
            if (attribute instanceof String strAttribute) {
                RequestContextHolder.currentRequestAttributes()
                        .setAttribute(TOKEN_HEADER_NAME, strAttribute, RequestAttributes.SCOPE_REQUEST);
                return strAttribute;
            }
        } catch (IllegalStateException e) {
            LOG.debug("Not in a request context: Creating new token for outgoing request.", e);
        }
        return UUID.randomUUID().toString();
    }
}

配置RestTemplate时注册该拦截器:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

import java.util.Collections;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(TokenRestTemplateInterceptor tokenInterceptor) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setInterceptors(Collections.singletonList(tokenInterceptor));
        return restTemplate;
    }

    @Bean
    public TokenRestTemplateInterceptor tokenRestTemplateInterceptor() {
        return new TokenRestTemplateInterceptor();
    }
}

内容的提问来源于stack exchange,提问作者François Poirier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:50:00