WebFlux中如何用onRetryExhaustedThrow返回原始Http状态码与消息?
WebFlux实现自定义重试并返回最后一次请求的错误详情
你的需求完全可以通过WebFlux实现,核心是在重试耗尽时,从最后一次失败的异常中提取真实的HTTP状态码、消息和响应体,而非硬编码错误信息。下面是修改后的代码及说明:
修改后的重试方法
private RetryBackoffSpec retryServerError() { return Retry.backoff(3, Duration.of(100, ChronoUnit.MILLIS)) .filter(this::isServerError) .onRetryExhaustedThrow((retrySpec, retrySignal) -> { // 获取触发重试耗尽的最后一次异常 Throwable lastFailure = retrySignal.failure(); if (lastFailure instanceof HttpServerErrorException serverErrorEx) { // 复用原异常的所有错误信息:状态码、消息、响应头、响应体 return new HttpServerErrorException( serverErrorEx.getStatusCode(), serverErrorEx.getStatusText(), serverErrorEx.getResponseHeaders(), serverErrorEx.getResponseBodyAsByteArray(), serverErrorEx.getCharset() ); } // 兜底处理,避免非预期异常导致问题 return new HttpServerErrorException(HttpStatus.SERVICE_UNAVAILABLE, "请求重试全部失败"); }); } private boolean isServerError(Throwable throwable) { return throwable instanceof HttpServerErrorException; }
原代码的问题与优化点
- 硬编码错误信息:原代码中重试耗尽时固定返回
SERVICE_UNAVAILABLE,丢失了最后一次请求真实的错误状态码和响应细节,修改后直接复用原异常的所有信息。 - 获取最后一次异常:通过
retrySignal.failure()可以拿到导致重试终止的最后一次失败异常,这是提取真实错误信息的关键。 - 保留响应体:
HttpServerErrorException本身已经包含响应体(可通过getResponseBodyAsString()或getResponseBodyAsByteArray()获取),直接传递这些信息到新抛出的异常中,上层就能拿到完整的错误详情。
保留原请求方法
你的post方法无需大幅修改,保持原逻辑即可:
public ResponseEntity<U> post(Class<Void> responseClass, Function<UriBuilder, URI> uri, MyBodyObject body) throws WebClientException, RestClientResponseException { return this.getWebClientBuilder() .build() .post() .uri(uri) .body(BodyInserters.fromValue(body)) .retrieve() .toEntity(responseClass) .retryWhen(retryServerError()) .block(); }
注意:WebClient的retrieve()方法默认会在收到5xx响应时抛出HttpServerErrorException,该异常包含完整的HTTP响应信息,这也是我们能提取到真实错误细节的基础。
内容的提问来源于stack exchange,提问作者Jérémy
相关产品推荐
相关产品推荐

