【发布时间】:2025-11-25 05:30:01
【问题描述】:
我们有一个服务器来检索 OAUTH 令牌,并通过 WebClient.filter 方法将 oauth 令牌添加到每个请求中 例如
webClient
.mutate()
.filter((request, next) -> tokenProvider.getBearerToken()
.map(token -> ClientRequest.from(request)
.headers(httpHeaders -> httpHeaders.set("Bearer", token))
.build()).flatMap(next::exchange))
.build();
TokenProvider.getBearerToken returns Mono<String> since it is a webclient request (this is cached)
我想要一个重试功能,在 401 错误时,将使令牌无效并再次尝试请求 我有这样的工作
webClient.post()
.uri(properties.getServiceRequestUrl())
.contentType(MediaType.APPLICATION_JSON)
.body(fromObject(createRequest))
.retrieve()
.bodyToMono(MyResponseObject.class)
.retryWhen(retryOnceOn401(provider))
private Retry<Object> retryOnceOn401(TokenProvider tokenProvider) {
return Retry.onlyIf(context -> context.exception() instanceof WebClientResponseException && ((WebClientResponseException) context.exception()).getStatusCode() == HttpStatus.UNAUTHORIZED)
.doOnRetry(objectRetryContext -> tokenProvider.invalidate());
}
有没有办法将其移至 webClient.mutate().....build() 函数? 以便所有请求都具有此重试功能?
我尝试添加为过滤器,但它似乎不起作用,例如
.filter(((request, next) -> next.exchange(request).retryWhen(retryOnceOn401(tokenProvider))))
对解决此问题的最佳方法有什么建议吗? 问候
【问题讨论】:
-
请提供有关“它不起作用”的更多信息 - 您是否遇到异常?您的重试函数是否被调用?令牌没有失效吗?能否提供
log()运算符的日志输出? -
嗨,布赖恩,我想我明白了。 webClient 不会在 401 上引发异常,因为这些仅在我调用 bodyToMono 后才会引发,因为这会检查 ClientResponse 的状态并在出现错误时引发 WebClientResponseException。所以在构建器上,retryWhen 永远不会被实际调用,因为没有抛出异常,我可以通过检查响应是 401 并抛出异常然后重试函数启动来完成这项工作。
-
很高兴听到!请回答您的问题,我相信这会对其他人有所帮助。
标签: spring-webflux project-reactor