【问题标题】:How to intercept a request when using SpringBoot WebClient使用 Spring Boot WebClient 时如何拦截请求
【发布时间】:2019-01-14 13:16:57
【问题描述】:

我正在尝试使用WebClient 来调用我的restServices。以前在RestTemplate 上,我们定义了ClientHttpRequestInterceptor 并将其附加到RestTemplate 以拦截和修改请求。使用WebClient,有没有办法做到这一点?

谢谢,

-Sreeni

【问题讨论】:

    标签: spring-boot spring-webflux


    【解决方案1】:

    当您使用 WebClient Builder 时,您可以使用 filter() 方法传入 ExchangeFilterFunction 接口的实现。这相当于ClientHttpRequestInterceptorRestTemplate

    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);
        };
    }
    

    【讨论】:

    • 我知道这在某种意义上可能相当于ClientHttpRequestInterceptor,但它并没有给你太多的访问权限。例如,您看不到请求的正文。
    【解决方案2】:

    在我的情况下,我需要从传入请求中获取一些标头并将它们放入我的请求中。我找到了我需要的东西here

    首先需要一个过滤器

    /**
     * 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,在我的情况下我需要 Auth 和 origin:

    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);
                });
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用 ExchangeFilterFunction 并在您正在使用的 WebClient 实例上配置它。有关更多信息,请参阅Spring Framework reference documentation

      【讨论】:

        猜你喜欢
        • 2018-07-11
        • 1970-01-01
        • 2020-11-19
        • 2018-08-09
        • 2013-03-17
        • 2020-04-14
        • 1970-01-01
        • 2019-11-21
        • 2019-02-04
        相关资源
        最近更新 更多