如何使用 Spring WebClient 以不同的 header 设置进行后续调用?
How to use Spring WebClient to make a subsequent call with different header setting?
我需要调用第三方 API,它需要事先进行身份验证调用以获取身份验证令牌。身份验证 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 来为您获取令牌 https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#webflux-client-filter
类似的东西(未经测试可能有错误):
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...
用 spring 配置包装所有内容:
@Configuration
public class WebClientConfiguration {
@Bean
public WebClient authWebClient(final WebClient.Builder webClientBuilder) {
return webClientBuilder.build();
}
@Bean
public ExchangeFilterFunction authFilter(final WebClient authWebClient) {
return (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.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()));
}
}
我需要调用第三方 API,它需要事先进行身份验证调用以获取身份验证令牌。身份验证 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 来为您获取令牌 https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web-reactive.html#webflux-client-filter
类似的东西(未经测试可能有错误):
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...
用 spring 配置包装所有内容:
@Configuration
public class WebClientConfiguration {
@Bean
public WebClient authWebClient(final WebClient.Builder webClientBuilder) {
return webClientBuilder.build();
}
@Bean
public ExchangeFilterFunction authFilter(final WebClient authWebClient) {
return (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.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()));
}
}