微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用Spring WebClient使用不同的标头设置进行后续调用?

如何解决如何使用Spring WebClient使用不同的标头设置进行后续调用?

我需要调用第三方API,该API需要事先进行身份验证才能获得身份验证令牌。 Authentication API在json中,但随后的调用在XML中。

我分别有:

webclient.post().uri("/auth").header(ACCEPT,JSON).retrieve()
      .bodyToMono(AuthToken.class);
webclient.post().uri("/api").header(ACCEPT,XML).header("AUTH",authToken).retrive().bodyToFlux();

我应该如何实现能够访问第二个API的方法? 我尝试使用token = firstCall.block()方法内分配变量,但出现block() is not supported错误

解决方法

您只需要像这样转换原始通量即可:

webclient.post().uri("/auth")
    .header(ACCEPT,JSON)
    .retrieve()
    .bodyToMono(AuthToken.class)
    .flatMapMany(authToken -> webclient.post().uri("/api")
    .header(ACCEPT,XML)
    .header("AUTH",authToken).retrive().bodyToFlux();

更好的解决方案是使用将为您https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#webflux-client-filter

提取令牌的ExchangeFilterFunction。

类似的东西(未经测试可能有错误):

WebClient authWebClient = WebClient.builder().build();
WebClient webClient = WebClient.builder()
        .filter(((request,next) -> authWebClient.post()
                .uri("/auth")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(AuthToken.class)
                .flatMap(authToken -> next.exchange(ClientRequest.from(request)
                        .headers(headers -> headers.add("AUTH",authToken))
                        .build()))
        ))
        .build();

webClient.post().uri("/api")
        .accept(MediaType.APPLICATION_XML)
        .retrieve()
        .bodyToFlux(MyData.class);

这是基本操作,但您可以添加缓存以避免令牌过期而再次请求或获取... 请注意,存在用于基本oauth2的内置ExchangeFilterFunction ...

使用弹簧配置包装一切:

@Configuration
public class WebClientConfiguration {
    @Bean
    public WebClient authWebClient(final WebClient.Builder webClientBuilder) {
        return webClientBuilder.build();
    }

    @Bean
    public ExchangeFilterFunction authFilter(final WebClient authWebClient) {
        return (request,authToken.toString()))
                        .build()));
    }

    @Bean
    public WebClient webClient(final WebClient.Builder webClientBuilder,final ExchangeFilterFunction authFilter) {
        return webClientBuilder
                .filter(authFilter)
                .build();
    }
}

或者,如果您想避免使用lambda:

@Configuration
public class WebClientConfiguration {
@Bean
    public WebClient authWebClient(final WebClient.Builder webClientBuilder) {
        return webClientBuilder.build();
    }

    @Bean
    public WebClient webClient(final WebClient.Builder webClientBuilder,final AuthFilter authFilter) {
        return webClientBuilder
                .filter(authFilter)
                .build();
    }
    
    @Bean
    public AuthFilter authFilter(WebClient authWebClient) {
        return new AuthFilter(authWebClient);
    }
}

public class AuthFilter implements ExchangeFilterFunction {

    private final WebClient authWebClient;

    public AuthFilter(WebClient authWebClient) {
        this.authWebClient = authWebClient;
    }

    @Override
    public Mono<ClientResponse> filter(final ClientRequest request,final ExchangeFunction next) {
        return authWebClient.post()
                .uri("/auth")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(AuthToken.class)
                .flatMap(authToken -> next.exchange(ClientRequest.from(request)
                        .headers(headers -> headers.add("AUTH",authToken.toString()))
                        .build()));
    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。