【发布时间】:2021-12-18 02:06:10
【问题描述】:
我有以下代码来发出将被重试最大次数的请求。此请求需要一个授权标头,我正在缓存此信息以防止此方法每次都调用该方法来检索此信息。
我想做的是:
- 调用 myMethod 时,我首先检索我正在调用的服务的登录信息,在大多数情况下,这些信息将来自调用 getAuthorizationHeaderValue 方法时的缓存。
- 在 Web 客户端中,如果发送此请求的响应返回 4xx 响应,我需要再次登录到我正在调用的服务,然后重试请求。为此,我正在调用 tryToLoginAgain 方法来再次设置标头的值。
- 在设置了标头之后,请求的重试应该可以工作了。
- 如果再次登录调用失败,我需要停止重试,因为重试请求没有用处。
public <T> T myMethod(...) {
...
try {
AtomicReference<String> headerValue = new AtomicReference<>(loginService.getAuthorizationHeaderValue());
Mono<T> monoResult = webclient.get()
.uri(uri)
.accept(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, headerValue.get())
.retrieve()
.onStatus(HttpStatus::is4xxClientError, response -> throwHttpClientLoginException())
.bodyToMono(type)
.doOnError(HttpClientLoginException.class, e -> tryToLoginAgain(headerValue))
.retryWhen(Retry.backoff(MAX_NUMBER_RETRIES, Duration.ofSeconds(5)));
result = monoResult.block();
} catch(Exception e) {
throw new HttpClientException("There was an error while sending the request");
}
return result;
}
...
private Mono<Throwable> throwHttpClientLoginException() {
return Mono.error(new HttpClientLoginException("Existing Authorization failed"));
}
private void tryToLoginAgain(AtomicReference<String> headerValue) {
loginService.removeAccessTokenFromCache();
headerValue.set(loginService.getAuthorizationHeaderValue());
}
我有一些单元测试并且快乐路径工作正常(第一次未授权,尝试再次登录并再次发送请求)但是登录根本不起作用的场景不起作用。
我认为如果 tryToLoginAgain 方法抛出一个异常,该异常会被我在 myMethod 中的 catch 捕获但它永远不会到达那里,它只是再次重试请求。有什么方法可以做我想做的事吗?
【问题讨论】:
标签: spring-boot spring-webflux project-reactor spring-webclient