异步 WebClient 请求的异常处理
Exception Handling for async WebClient request
最近我一直在使用WebClient。我正在创建同步请求和异步请求。在同步请求中,我能够捕获 WebClientResponseException 而当我尝试在异步请求中捕获 WebClientResponseException (也尝试使用通用异常,但没有用)时,它无法被捕获。我在互联网上找不到任何示例。我不确定在异步 WebClient 请求中是否可以进行此类异常处理。
以下是代码示例:
Sync Request(可以捕获异常的地方)
{
webClient
.post()
.uri(POST_ENDPOINT)
.bodyValue(cloudEvent)
.header("Authorization", token)
.retrieve()
.toEntity(String.class)
.block();
}
catch(final WebClientResponseException e)
{
log.error(String.valueOf(e));
throw new MyCustomException ("");
}
Async Request(无法捕获异常的地方)
try
{
stream=
webClient
.get()
.uri(GET_ENDPOINT)
.header("Authorization", token)
.retrieve()
.bodyToFlux(Any_Parametrized_Type_Reference);
}
catch(ffinal WebClientResponseException e)
{
log.error(String.valueOf(e));
throw new MyCustomException ("");
}
提前感谢您的回复。
Async表示进程会被转移到另一个线程。 bodyToFlux 将执行此操作并完成执行,但您对该线程没有任何控制权,因为在您当前的线程中,该函数已执行并且不会触发问题。
这类似于 JS 中的 Promises,您应该在任何异常情况下进行回调。
在 bodyToFlux 之后,您可以添加这些回调。
webClient.get()
.uri("https://baeldung.com/path")
.retrieve()
.bodyToFlux(JsonNode.class)
.timeout(Duration.ofSeconds(5))
.onErrorMap(ReadTimeoutException.class, ex -> new HttpTimeoutException("ReadTimeout"))
.onErrorReturn(SslHandshakeTimeoutException.class, new TextNode("SslHandshakeTimeout"))
.doOnError(WriteTimeoutException.class, ex -> log.error("WriteTimeout"))
onErrorMap、onErrorReturn 和 doOnError 收到您的回调并在出现异常时执行 lambda 方法。
更多信息在这里:https://www.baeldung.com/spring-webflux-timeout#exception-handling
感谢@CarlosCárdenas;当我在本地测试时,以下更改对我有用。
private static final Function<WebClientRequestException, MyCustomException>
EXCEPTION_MAPPER =
ex ->
new MyCustomException(ex.getCause());
webClient
.get()
.uri(GET_ENDPOINT)
.header("Authorization", token)
.retrieve()
.bodyToFlux(Any_Parametrized_Type_Reference)
.onErrorMap(WebClientRequestException.class, EXCEPTION_MAPPER)
.doOnError(MyCustomException.class, ex -> myExceptionHandlingMethod(ex));
目前,我遇到了相关单元测试的问题。它不应该抛出异常,所以我无法捕获异常。我想我遗漏了一些关于测试异步流程的内容。我的测试看起来像这样:
@Test
void myTest()
{
// Given
…
//When
final Executable executeMyMethod=
() -> myMethod(parameter1, parameter2);
// Then
// await().pollDelay(Duration.FIVE_SECONDS).untilAsserted(() -> assertTrue(true)); -> I’m not sure if it is needed or not
assertThrows(MyCustomException.class, executeMyMethod);
}
最近我一直在使用WebClient。我正在创建同步请求和异步请求。在同步请求中,我能够捕获 WebClientResponseException 而当我尝试在异步请求中捕获 WebClientResponseException (也尝试使用通用异常,但没有用)时,它无法被捕获。我在互联网上找不到任何示例。我不确定在异步 WebClient 请求中是否可以进行此类异常处理。
以下是代码示例:
Sync Request(可以捕获异常的地方)
{
webClient
.post()
.uri(POST_ENDPOINT)
.bodyValue(cloudEvent)
.header("Authorization", token)
.retrieve()
.toEntity(String.class)
.block();
}
catch(final WebClientResponseException e)
{
log.error(String.valueOf(e));
throw new MyCustomException ("");
}
Async Request(无法捕获异常的地方)
try
{
stream=
webClient
.get()
.uri(GET_ENDPOINT)
.header("Authorization", token)
.retrieve()
.bodyToFlux(Any_Parametrized_Type_Reference);
}
catch(ffinal WebClientResponseException e)
{
log.error(String.valueOf(e));
throw new MyCustomException ("");
}
提前感谢您的回复。
Async表示进程会被转移到另一个线程。 bodyToFlux 将执行此操作并完成执行,但您对该线程没有任何控制权,因为在您当前的线程中,该函数已执行并且不会触发问题。
这类似于 JS 中的 Promises,您应该在任何异常情况下进行回调。
在 bodyToFlux 之后,您可以添加这些回调。
webClient.get()
.uri("https://baeldung.com/path")
.retrieve()
.bodyToFlux(JsonNode.class)
.timeout(Duration.ofSeconds(5))
.onErrorMap(ReadTimeoutException.class, ex -> new HttpTimeoutException("ReadTimeout"))
.onErrorReturn(SslHandshakeTimeoutException.class, new TextNode("SslHandshakeTimeout"))
.doOnError(WriteTimeoutException.class, ex -> log.error("WriteTimeout"))
onErrorMap、onErrorReturn 和 doOnError 收到您的回调并在出现异常时执行 lambda 方法。
更多信息在这里:https://www.baeldung.com/spring-webflux-timeout#exception-handling
感谢@CarlosCárdenas;当我在本地测试时,以下更改对我有用。
private static final Function<WebClientRequestException, MyCustomException>
EXCEPTION_MAPPER =
ex ->
new MyCustomException(ex.getCause());
webClient
.get()
.uri(GET_ENDPOINT)
.header("Authorization", token)
.retrieve()
.bodyToFlux(Any_Parametrized_Type_Reference)
.onErrorMap(WebClientRequestException.class, EXCEPTION_MAPPER)
.doOnError(MyCustomException.class, ex -> myExceptionHandlingMethod(ex));
目前,我遇到了相关单元测试的问题。它不应该抛出异常,所以我无法捕获异常。我想我遗漏了一些关于测试异步流程的内容。我的测试看起来像这样:
@Test
void myTest()
{
// Given
…
//When
final Executable executeMyMethod=
() -> myMethod(parameter1, parameter2);
// Then
// await().pollDelay(Duration.FIVE_SECONDS).untilAsserted(() -> assertTrue(true)); -> I’m not sure if it is needed or not
assertThrows(MyCustomException.class, executeMyMethod);
}