问题描述
我需要调用第三方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();
提取令牌的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()));
}
}