From 1d858eb6c158e98adafd736d488def8b636d3952 Mon Sep 17 00:00:00 2001 From: asahi Date: Tue, 15 Apr 2025 12:45:54 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20Exceptions.propagate=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E9=98=85=E8=AF=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring/webflux/Reactor.md | 61 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/spring/webflux/Reactor.md b/spring/webflux/Reactor.md index 523a1f6..8818a99 100644 --- a/spring/webflux/Reactor.md +++ b/spring/webflux/Reactor.md @@ -64,6 +64,8 @@ - [retry helper](#retry-helper) - [retrying with transient errors](#retrying-with-transient-errors) - [handling Exceptions in operators or functions](#handling-exceptions-in-operators-or-functions) + - [checked exception](#checked-exception) + - [Exceptions Utility](#exceptions-utility) >>>>>>> 8d41980 (doc: 阅读transient errors文档) # Reactor @@ -992,3 +994,62 @@ assertThat(errorCount).hasValue(6); > `transientErrors`主要是为了处理周期性发生异常,异常能够重试成功,并且发生异常后一段时间平稳运行的场景 #### handling Exceptions in operators or functions +通常来说,operator的执行有可能会抛出异常,根据抛出异常类型的不同,存在如何区别: +- `unchecked Exception`:对于抛出的`unchecked exception`,其都会通过`onError`向下游传递,例如,map operator中抛出的`RuntimeException`将会被转化为对下游`onError`的调用 + ```java + Flux.just("foo") + .map(s -> { throw new IllegalArgumentException(s); }) + .subscribe(v -> System.out.println("GOT VALUE"), + e -> System.out.println("ERROR: " + e)); + ``` + 上述代码示例将会触发下游subscriber的onError,输出内容如下: + ```console + ERROR: java.lang.IllegalArgumentException: foo + ``` +- `fatal exceptions`:在reactor中,定义了一些被视为`致命`的异常(例如`OutOfMemoryError`),具体的`fatal`异常包含范围可见`Exceptions.throwIfFatal` + - 在抛出`fatal error`时,reactor operator会抛出异常而不是将其传递到下游 + + +##### checked exception +对于`checked exception`,当调用方法签名中指定了`throws xxxException`的方法时,需要通过`try-catch block`对其进行处理。对于`checked exception`,有如下选择: +- 对异常进行捕获,并且对其执行`recover`操作,sequence会继续执行 +- 对异常进行捕获,并且封装到`unchecked exception`中,并将`unchecked exception`进行rethrow(这将对sequence进行打断) +- 如果需要返回一个`Flux`(例如,使用`flatMap`方法),可以使用`Flux.error(checkedException)`返回一个`error-producing Flux`(sequence会终止) + +##### Exceptions Utility +通过reactor提供的Exceptions Utility,可以保证`仅当异常为checked exception时,才会封装` +- `Exceptions.propagate`在必要时会封装exception。 + - 其并不会对`RuntimeException`进行封装,并且该方法首先会调用`throwIfFatal` + - 该方法会将checked exception封装到`reactor.core.Exceptions.ReactiveException`中 +- `Exceptions.unwrap`: + - 该方法会获取original unwrapped exception + +使用示例如下所示: +```java +public String convert(int i) throws IOException { + if (i > 3) { + throw new IOException("boom " + i); + } + return "OK " + i; +} + +Flux converted = Flux + .range(1, 10) + .map(i -> { + try { return convert(i); } + catch (IOException e) { throw Exceptions.propagate(e); } + }); + +converted.subscribe( + v -> System.out.println("RECEIVED: " + v), + e -> { + if (Exceptions.unwrap(e) instanceof IOException) { + System.out.println("Something bad happened with I/O"); + } else { + System.out.println("Something bad happened"); + } + } +); +``` + +