我一直在寻找以下用例的解决方案,但没有成功,我希望有人能帮助我:
假设以下用例。我需要调用customer (customerApi),这个Api需要一个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的reactor-extra,但是这个包中的好的旧retryWhen现在被废弃了(基于:Adding a retry all requests of WebClient的解决方案)。
发布于 2020-10-20 18:29:19
该方法
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()));
}此外,我不认为在重试添加授权令牌时试图操作头的方式是实现这一目标的正确方法。你必须想出一个更好的解决方案/设计。
https://stackoverflow.com/questions/64355088
复制相似问题