使用 Spring WebClient 重试时添加新标头

xBe*_*ntu 3 spring request-headers spring-retry spring-boot spring-webclient

webclientbuilder.baseUrl(url)
                .defaultHeaders(headers -> headers.addAll(requestHeader))
                .build()
                .post()
                .uri("/uri")
                .bodyValue(data)
                .exchange()
                .flatMap(response  -> {
                                if(response.statusCode() == HttpStatus.UNAUTHORIZED){
                                                //retry with updated token in header
                                }
                })
                //return bodyToMono of specific object when retry is done or if
                //response status is 2xx
Run Code Online (Sandbox Code Playgroud)

任何有关如何处理此问题的建议将不胜感激!正如评论所说,如果 statusCode 为 UNAUTHORIZED,并且如果 statusCode 为 2xx,则在重试 post 请求之前,我需要将新令牌添加到标头,然后返回 bodyToMono。

And*_*rei 8

您可以通过向网络客户端添加过滤器来解决此问题:

public ExchangeFilterFunction retryOn401() {
    return (request, next) -> next.exchange(request)
            .flatMap((Function<ClientResponse, Mono<ClientResponse>>) clientResponse -> {
                if (clientResponse.statusCode() == HttpStatus.UNAUTHORIZED) {
                    return authClient.getUpdatedToken() //here you get a Mono with a new & valid token
                            .map(token -> ClientRequest
                                    .from(request)
                                    .headers(headers -> headers.replace("Authorization", Collections.singletonList("Bearer " + token)))
                                    .build())
                            .flatMap(next::exchange);
                } else {
                    return Mono.just(clientResponse);
                }
            });
}
Run Code Online (Sandbox Code Playgroud)

因此,当 Web 客户端重试未经授权的请求时,它可以获取新令牌并将其设置在标头上,然后再执行重试。确保将其添加到网络客户端:

webclientbuilder.baseUrl(url)
            .defaultHeaders(headers -> headers.addAll(requestHeader))
            .filter(retryOn401())
            .build();
Run Code Online (Sandbox Code Playgroud)