Spring WebClient:在重试中调用方法 [英] Spring WebClient : Call method in retry

查看:17
本文介绍了Spring WebClient:在重试中调用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找以下用例的解决方案,但没有成功,希望有人能帮忙:

假设以下用例。我需要调用一个客户Api(customerApi),该接口需要一个Bearer令牌,该令牌在我调用customerApi时可能已经过期。如果令牌已过期,customerApi将返回401响应。

我想做的是,如果我收到401并调用该方法以获得新的Bearer令牌,则只重试一次。如果重试仍然返回401,我需要抛出Exception

获取Bearer令牌的方法:

private String getToken() {
    return oAuthService.getToken();
}

webClient调用的用法customerApi(customerWebClient是用WebClient.Builder创建的Bean):

public Customer getCustomerById(String customerId, String token) {
        return customerWebClient.get()
            .uri("myurl/customers/{customerId}, customerId)
            .headers(httpHeaders -> {
                httpHeaders.add(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            })
            .retrieve()
            .bodyToMono(Customer.class)
            .onErrorResume(WebClientResponseException.NotFound.class, notFound ->
                        Mono.error(new MyCustomException()))
            .block();
    }

似乎retryWhen只能用于升级超时。所以我希望有人知道如何实现这个用例^^

感谢您的帮助:)

编辑:

我尝试使用reactor-extra中的retryWhen(Retry.onlyIf(...)),但此包中的好旧retryWhen现在已弃用(基于Adding a retry all requests of WebClient的解决方案)

推荐答案

方法

public final Mono<T> retryWhen(Function<Flux<Throwable>, ? extends Publisher<?>> whenFactory)

已弃用,现在首选的方法是

public final Mono<T> retryWhen(Retry retrySpec)

因此,您可以将代码修改为如下所示,以使其与新的retryWhen

一起工作
public Customer getCustomerById(String customerId, String token) {

    HttpHeaders headers = new HttpHeaders();
    headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + token);

    final RetrySpec retrySpec = Retry.max(1).doBeforeRetry(
        retrySignal -> headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + someTokenGetterMethod()))
        .filter(throwable -> throwable.getClass() == Unauthorized.class);

    return Mono.defer(() -> webClient.get().uri("myurl/customers/{customerId}, customerId")
        .headers(httpHeaders -> httpHeaders.addAll(headers))
        .retrieve()
        .bodyToMono(Customer.class))
        .retryWhen(retrySpec)
        .onErrorResume(WebClientResponseException.NotFound.class,
            notFound -> Mono.error(new MyCustomException()))
        .block();
}

以下是使用https://httpbin.org/

public CommandLineRunner commandLineRunner() {

    HttpHeaders headers = new HttpHeaders();

    final RetrySpec retrySpec = Retry.max(1).doBeforeRetry(
        retrySignal -> headers.add("Authorization", "Bearer 1234")).filter(
        throwable -> throwable.getClass() == Unauthorized.class);

    return args -> Mono.defer(() -> webClient.get().uri("https://httpbin.org/bearer")
        .headers(httpHeaders -> httpHeaders.addAll(headers)).retrieve().toEntity(Map.class)
        .retryWhen(retrySpec)
        .subscribe(objectResponseEntity -> System.out
            .println("objectResponseEntity = " + objectResponseEntity.getBody()));
}
此外,我不认为在重试添加授权令牌时试图操纵标头的方式是实现这一点的正确方式。你必须想出一个更好的解决方案/设计。

这篇关于Spring WebClient:在重试中调用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆