You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebClient如何在onStatus()中调用自定义方法后再抛出异常

实现方案

步骤1:改造补偿方法为非阻塞实现(推荐)

原有deleteTransaction方法内部使用block()会阻塞响应式线程,不符合WebClient的响应式编程规范,调整为返回Mono类型:

private Mono<String> deleteTransaction(Integer transactionID) {
    return webclient.delete()
            .uri(uriBuilder -> uriBuilder
                    .path(url + "/" + transactionID + "/delete").build())
            .header(HttpHeaders.AUTHORIZATION, "Bearer " + clientProfile.getJwt().getTokenValue())
            .retrieve()
            .bodyToMono(String.class);
}

步骤2:修改onStatus异常处理逻辑

在onStatus的回调中,先调用补偿方法执行撤销操作,待补偿执行完成后再抛出对应业务异常,注意将代码中的yourTransactionId替换为实际业务上下文中的交易ID参数:

webclient
        .post()
        .uri(url, chargeSeqId)
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON)
        .acceptCharset(Charset.forName("UTF-8"))
        .header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
        .body(BodyInserters.fromValue(pojos))
        .retrieve()
        .onStatus(HttpStatus::is4xxClientError,
                res -> res.bodyToMono(String.class)
                        .flatMap(error -> deleteTransaction(yourTransactionId)
                                // 补偿执行完成后抛出业务异常
                                .then(Mono.error(new DataValidationException(error))))
        )
        .onStatus(HttpStatus::is5xxServerError,
                res -> res.bodyToMono(String.class)
                        .flatMap(error -> deleteTransaction(yourTransactionId)
                                .then(Mono.error(new SystemException(error))))
        )
        .bodyToMono(MyPojos[].class)
        .block();

可选:补偿异常兜底处理

如果需要处理补偿方法本身调用失败的场景,可以增加异常捕获逻辑:

.onStatus(HttpStatus::is4xxClientError,
        res -> res.bodyToMono(String.class)
                .flatMap(error -> deleteTransaction(yourTransactionId)
                        // 补偿调用失败时的兜底处理
                        .onErrorResume(compensateErr -> {
                            log.error("补偿交易执行失败,交易ID:{}", yourTransactionId, compensateErr);
                            // 可根据业务需求选择抛出原异常或补偿异常
                            return Mono.error(new DataValidationException("原请求失败,且补偿执行失败:" + error, compensateErr));
                        })
                        .then(Mono.error(new DataValidationException(error)))
                )
)

兼容方案:保留原有阻塞补偿方法

如果不想调整原有deleteTransaction的实现,也可以直接在回调中调用(不推荐,会阻塞响应式IO线程):

.onStatus(HttpStatus::is4xxClientError,
        res -> res.bodyToMono(String.class)
                .flatMap(error -> {
                    // 执行阻塞补偿调用
                    String compensateAck = deleteTransaction(yourTransactionId);
                    log.info("补偿执行结果:{}", compensateAck);
                    return Mono.error(new DataValidationException(error));
                })
)

内容的提问来源于stack exchange,提问作者user1250720

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 20:24:02