使用SpringBoot WebClient时如何拦截请求

问题描述 投票:0回答:3

我正在尝试使用

WebClient
来调用我的restServices。之前在
RestTemplate
上,我们定义了
ClientHttpRequestInterceptor
并将其附加到
RestTemplate
来拦截和修改请求。对于
WebClient
,有没有办法做到同样的事情?

谢谢,

-斯雷尼

spring-boot spring-webflux
3个回答
18
投票

当您使用 WebClient Builder 时,您可以使用

ExchangeFilterFunction
方法传入
filter()
接口的实现。这相当于
ClientHttpRequestInterceptor
RestTemplate

WebClient 构建器文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.Builder.html#filter-org。 springframework.web.reactive.function.client.ExchangeFilterFunction-

ExchangeFilterFunction 文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/function/client/ExchangeFilterFunction.html

例如:

WebClient webClient = WebClient.builder()
        .baseUrl("http://localhost:8080|)
        .filter(logFilter())
        .build();


private ExchangeFilterFunction logFilter() {
    return (clientRequest, next) -> {
        logger.info("External Request to {}", clientRequest.url());
        return next.exchange(clientRequest);
    };
}

11
投票

就我而言,我需要从传入请求中获取一些标头并将它们放入我的请求中。我在这里找到了我需要的东西。

首先需要一个过滤器

/** * ReactiveRequestContextFilter * * @author L.cm */ @Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) public class ReactiveRequestContextFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); return chain.filter(exchange) .subscriberContext(ctx -> ctx.put(ReactiveRequestContextHolder.CONTEXT_KEY, request)); } }
还有

ReactiveRequestContextHolder


/** * ReactiveRequestContextHolder * * @author L.cm */ public class ReactiveRequestContextHolder { static final Class<ServerHttpRequest> CONTEXT_KEY = ServerHttpRequest.class; /** * Gets the {@code Mono<ServerHttpRequest>} from Reactor {@link Context} * @return the {@code Mono<ServerHttpRequest>} */ public static Mono<ServerHttpRequest> getRequest() { return Mono.subscriberContext() .map(ctx -> ctx.get(CONTEXT_KEY)); } }
最后就像 Michael McFadyen 说的,你需要配置一个 

ExchangeFilterFunction

,就我而言,我需要身份验证和来源:

private ExchangeFilterFunction headerFilter() { return (request, next) -> ReactiveRequestContextHolder.getRequest() .flatMap(r -> { ClientRequest clientRequest = ClientRequest.from(request) .headers(headers -> { headers.set(HttpHeaders.ORIGIN, r.getHeaders().getFirst(HttpHeaders.ORIGIN)); headers.set(HttpHeaders.AUTHORIZATION, r.getHeaders().getFirst(HttpHeaders.AUTHORIZATION)); }) .build(); return next.exchange(clientRequest); }); }
编辑:在项目reactor的较新版本中

Mono.subscriberContext()

不存在。必须用 
Mono.deferContextual(Mono::just)
 更改,并且 
.subscriberContext(ctx -> ...)
.contextWrite(ctx -> ...)
 更改
    


4
投票
您可以使用

ExchangeFilterFunction

 并在您正在使用的 
WebClient
 实例上配置它。有关更多信息,请参阅 
Spring 框架参考文档

© www.soinside.com 2019 - 2024. All rights reserved.