如何在 Spring Webclient 中调用 onStatus() 中的方法

How to call a method inside onStatus() in Spring Webclient

目前,我只是在响应代码为 4XX 或 5XX 时在 onStatus() 中抛出异常。但是,我想调用另一个服务(一个补偿事务来撤消更改)然后抛出一个异常。

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 -> Mono.error(new DataValidationException(error))))
            .onStatus(HttpStatus::is5xxServerError,
                    res -> res.bodyToMono(String.class).flatMap(error -> Mono.error(new SystemException(error))))
            .bodyToMono(MyPojos[].class)
            .block();

我想在响应代码为 4XX 或 5XX 时调用以下方法,然后再抛出 DataValidationException() 或 SystemException()。

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

您可以使用 deleteTransaction 方法 return 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);
}

然后就可以在需要的地方非阻塞的调用这个方法了。另外,由于我不知道您实际想要传递给 deleteTransaction 方法的是什么,因此我已将 chargeSeqId 传递给它。


     .onStatus(HttpStatus::is4xxClientError,
             res -> {
                    var ackMono = deleteTransaction(chargeSeqId); // replace with required input
                    var resBodyMono = res.bodyToMono(String.class);
                    return Mono.zip(ackMono, resBodyMono, (ack,resBody)->Mono.error(new DataValidationException(resBody)));
                    })
                             

对于 is5xxServerError 也可以这样做。