【发布时间】:2021-08-02 14:40:03
【问题描述】:
我正在使用 Spring WebFlux 中的 WebClient 与 Spring 客户端的 REST API 后端进行通信。
当此 REST API 后端引发异常时,它会以我想从我的客户端收集的特定格式 (ErrorDTO) 进行响应。
我试图做的是让我的客户端在服务器以 5xx HTTP 状态代码回答时抛出包含此主体的 GestionUtilisateurErrorException(ErreurDTO)。
我尝试了几种选择:
我/onStatus
@Autowired
WebClient gestionUtilisateursRestClient;
gestionUtilisateursRestClient
.post()
.uri(profilUri)
.body(Mono.just(utilisateur), UtilisateurDTO.class)
.retrieve()
.onStatus(HttpStatus::is5xxServerError,
response -> {
ErreurDTO erreur = response.bodyToMono(ErreurDTO.class).block();
return Mono.error(new GestionUtilisateursErrorException(erreur));
}
)
.bodyToMono(Void.class)
.timeout(Duration.ofMillis(5000))
.block();
此方法不起作用,因为 webclient 不允许我调用 onStatus 中的 block 方法。我只能得到一个 Mono 对象,我不能从这里走得更远。
似乎“onStatus”方法不能在 WebClient 阻塞方法中使用,这意味着我可以抛出自定义异常,但我无法使用响应正文中的数据填充它。
II/ ExchangeFilterFunction
@Bean
WebClient gestionUtilisateursRestClient() {
return WebClient.builder()
.baseUrl(gestionUtilisateursApiUrl)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.filter(ExchangeFilterFunction.ofResponseProcessor(this::gestionUtilisateursExceptionFilter))
.build();
}
private Mono<ClientResponse> gestionUtilisateursExceptionFilter(ClientResponse clientResponse) {
if(clientResponse.statusCode().isError()){
return clientResponse.bodyToMono(ErreurDTO.class)
.flatMap(erreurDto -> Mono.error(new GestionUtilisateursErrorException(
erreurDto
)));
}
return Mono.just(clientResponse);
}
此方法有效,但抛出了一个我正在努力正确捕获的 reactor.core.Exceptions$ReactiveException(reactor.core.Exceptions 不可捕获,并且 ReactiveException 是私有的)。
此异常在其原因中包含我需要捕获的异常 (GestionUtilisateurErrorException),但我需要一种方法来正确捕获它。
我也尝试使用“onErrorMap”和“onErrorResume”方法,但它们都没有按我需要的方式工作。
编辑 1: 我现在正在使用以下解决方法,即使我觉得这是一种肮脏的方式来做我需要的事情:
gestionUtilisateursRestClient
.post()
.uri(profilUri)
.body(Mono.just(utilisateur), UtilisateurDTO.class)
.retrieve()
.onStatus(h -> h.is5xxServerError(),
response -> {
return response.bodyToMono(ErreurDTO.class).handle((erreur, handler) -> {
LOGGER.error(erreur.getMessage());
handler.error(new GestionUtilisateursErrorException(erreur));
});
}
)
.bodyToMono(String.class)
.timeout(Duration.ofMillis(5000))
.block();
}
catch(Exception e) {
LOGGER.debug("Erreur lors de l'appel vers l'API GestionUtilisateur (...)");
if(ExceptionUtils.getRootCause(e) instanceof GestionUtilisateursErrorException) {
throw((GestionUtilisateursErrorException) e.getCause());
}
else {
throw e;
}
}
在这里,它抛出了我可以同步处理的预期 GestionUtilisateursErrorException。
我可能会在全局处理程序中实现这一点,以避免在每次调用我的 API 时编写此代码。
谢谢。 凯文
【问题讨论】:
标签: rest exception spring-webclient