使用 WebFlux 调用 Restful 服务的错误处理示例
Example of error handling calling Restful services with WebFlux
我正在寻找使用 WebFlux 进行错误处理的简单示例。我在网上看了很多东西,但找不到适合我想要的东西。
我是 运行 Spring Boot 2.45
我这样调用服务:
Mono<ResponseObject> mono = webClient.post()
.uri(url.toString())
.header("Authorization", authToken)
.body(Mono.just(contract), contract.getClass())
.retrieve()
.bodyToMono(ResponseObject.class);
我的所有服务 return Json 反序列化为 ResposeObject,看起来像这样:
"success" : true,
"httpStatus": 200,
"messages" : [
"Informational message or, if not 200, then error messages"
],
result: {
"data": {}
}
data 只是作为服务调用结果的对象映射。
如果有错误,显然success是false.
当我最终执行 ResponseObject response = mono.block()
时,我希望每次都获得一个 ResponseObject,即使出现错误也是如此。我的服务 return 是一个 ResponseObject 即使它 return 的 http 状态为 400,但 WebFlux 似乎拦截了它并抛出异常。显然,甚至没有调用服务的地方也可能出现 400 和 500 错误。但我仍然想将收到的任何消息包装到 ResponseObject 中。如何消除所有异常并始终获得 ResponseObject returned?
更新
只是想澄清一下,该服务本身不是 Reactive Webflux 服务。它 不是 return 单声道。相反,它正在调用其他 Restful 服务,我想使用 Webflux 来做到这一点。所以我要做的是调用外部服务,然后该服务执行 block()。在大多数情况下,我会调用多个服务,然后执行 Mono.zip 并调用 block() 来等待所有服务。
这似乎是我想做的事情:,但仍然无法正常工作。不确定 exchange() 是什么
正确的处理方法是通过 .onErrorResume
,它允许您在发生任何错误时使用函数订阅后备发布者。您可以查看生成的异常和 return 自定义回退响应。
你可以这样做:
Mono<ResponseObject> mono = webClient.post()
.uri(url.toString())
.header("Authorization", authToken)
.bodyValue(contract)
.exchangeToMono(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(ResponseObject.class);
}
else if (response.statusCode().is4xxClientError()) {
return response.bodyToMono(ResponseObject.class);
}
else {
Mono<WebClientResponseException> wcre = response.createException();
// examine wcre and create custom ResponseObject
ResponseObject customRO = new ResponseObject();
customRO.setSuccess(false);
customRO.setHttpStatus(response.rawStatusCode());
// you can set more default properties in response here
return Mono.just( customRO );
}
});
此外,您不应在 Java 代码中的任何地方使用 .block()
。只需确保从您的 REST 控制器 return a Mono<ResponseObject>
即可。如果你想在 returning 到客户端之前检查响应,你可以在管道末尾的 .map()
处理程序中这样做(就在 .onErrorResume
处理程序之后)
.map(response -> {
// examine content of response
// in the end just return it
return response;
});
我正在寻找使用 WebFlux 进行错误处理的简单示例。我在网上看了很多东西,但找不到适合我想要的东西。
我是 运行 Spring Boot 2.45
我这样调用服务:
Mono<ResponseObject> mono = webClient.post()
.uri(url.toString())
.header("Authorization", authToken)
.body(Mono.just(contract), contract.getClass())
.retrieve()
.bodyToMono(ResponseObject.class);
我的所有服务 return Json 反序列化为 ResposeObject,看起来像这样:
"success" : true,
"httpStatus": 200,
"messages" : [
"Informational message or, if not 200, then error messages"
],
result: {
"data": {}
}
data 只是作为服务调用结果的对象映射。 如果有错误,显然success是false.
当我最终执行 ResponseObject response = mono.block()
时,我希望每次都获得一个 ResponseObject,即使出现错误也是如此。我的服务 return 是一个 ResponseObject 即使它 return 的 http 状态为 400,但 WebFlux 似乎拦截了它并抛出异常。显然,甚至没有调用服务的地方也可能出现 400 和 500 错误。但我仍然想将收到的任何消息包装到 ResponseObject 中。如何消除所有异常并始终获得 ResponseObject returned?
更新 只是想澄清一下,该服务本身不是 Reactive Webflux 服务。它 不是 return 单声道。相反,它正在调用其他 Restful 服务,我想使用 Webflux 来做到这一点。所以我要做的是调用外部服务,然后该服务执行 block()。在大多数情况下,我会调用多个服务,然后执行 Mono.zip 并调用 block() 来等待所有服务。
这似乎是我想做的事情:
正确的处理方法是通过 .onErrorResume
,它允许您在发生任何错误时使用函数订阅后备发布者。您可以查看生成的异常和 return 自定义回退响应。
你可以这样做:
Mono<ResponseObject> mono = webClient.post()
.uri(url.toString())
.header("Authorization", authToken)
.bodyValue(contract)
.exchangeToMono(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(ResponseObject.class);
}
else if (response.statusCode().is4xxClientError()) {
return response.bodyToMono(ResponseObject.class);
}
else {
Mono<WebClientResponseException> wcre = response.createException();
// examine wcre and create custom ResponseObject
ResponseObject customRO = new ResponseObject();
customRO.setSuccess(false);
customRO.setHttpStatus(response.rawStatusCode());
// you can set more default properties in response here
return Mono.just( customRO );
}
});
此外,您不应在 Java 代码中的任何地方使用 .block()
。只需确保从您的 REST 控制器 return a Mono<ResponseObject>
即可。如果你想在 returning 到客户端之前检查响应,你可以在管道末尾的 .map()
处理程序中这样做(就在 .onErrorResume
处理程序之后)
.map(response -> {
// examine content of response
// in the end just return it
return response;
});