当前位置: 首页 > 知识库问答 >
问题:

spring WebClient:在重试中调用方法

鞠侯林
2023-03-14

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

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

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

获取承载令牌的方法:

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

和调用CustomerAPIWebClient用法(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只能用于升级超时。所以我希望有人知道如何实现这个用例^^

感谢您的帮助:)

编辑:

我尝试使用retrywhen(retry.onlyif(...))retrywhenretrywhenretrywhenretrywhen(retry.onlyif(...)),但现在不推荐使用此包中的旧的retrywhen(基于以下

共有1个答案

胥良平
2023-03-14

方法

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

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

public final Mono<T> retryWhen(Retry retrySpec)

因此,您可以将代码修改为如下所示,使其与新的RetryWhen一起工作

java prettyprint-override">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()));
}

此外,我不认为您试图在重试中操作头以添加授权令牌的方式是实现这一点的正确方法。你必须想出一个更好的解决方案/设计。

 类似资料:
  • SOFARPC 支持进行框架层面的重试策略,前提是集群模式为 FailOver(SOFARPC 默认即为 FailOver 模式)。重试只有在发生服务端的框架层面异常或者是超时异常才会发起。如果是业务抛出异常,是不会重试的。默认情况下 SOFARPC 不进行任何重试。 请注意:超时异常虽然可以重试,但是需要服务端保证业务的幂等性,否则可能会有风险 XML 方式 如果使用 XML 方式订阅服务,可以

  • 问题内容: 在Eclipse中调试时如何调用类实例方法? 例如,假设我有以下代码: 我在canvas.drawColor行上有一个断点。当我调试时,代码停止在那一行,并且我可以查看canvas内的变量,但是我也希望能够像在Visual Studio中那样调用canvas内的方法以查看它们返回的结果? 问题答案: 打开“ 显示” 视图,在其中键入要执行的代码,选择它,单击鼠标右键,然后根据您要 执行

  • 我必须使用WebClient进行分页API调用,并最终组合所有结果。例如:个人最新1000交易详情。在一次调用中,我将在json响应(List)中获得最大100个对象。这个人最多只能得到1000条记录。 在伪代码java中,它可能看起来像这样 如何在SpringMVC中以反应式方式编写相同的内容而不阻塞? 像这样的东西???我不知道。帮助我

  • 我最终做的是在测试设置过程中替换应用程序级图(MockRestAdapter就是在其中创建的

  • 我有一个Foo和Bar对象的列表,以及每个相应对象的转换器。 Convert-method需要有所不同,因为Bar1与Bar2和Bar3等有很大不同,但是我想创建一个方法来处理所有可能的列表。 是否可以创建一个泛型方法,根据列表的内容调用相应的非泛型方法? 到目前为止,我已经尝试过了: 但这并不能编译,因为"无法解析方法'Converts(T, S)'" 有什么想法吗?

  • 问题内容: 最初,我有一个类来存储一些处理后的值,并将其与其他方法重用。 问题是,当我尝试将类方法划分为多个进程以加快速度时,python生成了进程,但它似乎不起作用(正如我在“任务管理器”中看到的那样,只有1个进程在运行)并且结果从未交付。 我进行了几次搜索,发现pathos.multiprocessing可以代替它,但是我想知道标准库是否可以解决这个问题? 问题答案: 您的代码失败了,因为它无