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
相关产品推荐
相关产品推荐

