doc: 阅读spring reactor文档
This commit is contained in:
@@ -51,6 +51,13 @@
|
|||||||
- [static fallback value](#static-fallback-value)
|
- [static fallback value](#static-fallback-value)
|
||||||
- [catch and swallow error](#catch-and-swallow-error)
|
- [catch and swallow error](#catch-and-swallow-error)
|
||||||
- [fallback method](#fallback-method)
|
- [fallback method](#fallback-method)
|
||||||
|
- [Dynamic Fallback Value](#dynamic-fallback-value)
|
||||||
|
- [Catch and rethrow](#catch-and-rethrow)
|
||||||
|
- [log and react on the side](#log-and-react-on-the-side)
|
||||||
|
- [doOnError](#doonerror)
|
||||||
|
- [Using resources and the finally block](#using-resources-and-the-finally-block)
|
||||||
|
- [doFinally](#dofinally)
|
||||||
|
- [using](#using)
|
||||||
|
|
||||||
# Reactor
|
# Reactor
|
||||||
## Reactive Programming
|
## Reactive Programming
|
||||||
@@ -758,5 +765,150 @@ Flux.just("timeout1", "unknown", "key2")
|
|||||||
```
|
```
|
||||||
> 在上述示例中,`Flux.error`会重新抛出上述异常
|
> 在上述示例中,`Flux.error`会重新抛出上述异常
|
||||||
|
|
||||||
|
#### Dynamic Fallback Value
|
||||||
|
当出现error时,如果并不想调用下游的`onError`,而是想给下游一个`根据异常信息计算出的默认值`,同样可以使用`onErrorResume`方法,示例如下:
|
||||||
|
```java
|
||||||
|
try {
|
||||||
|
Value v = erroringMethod();
|
||||||
|
return MyWrapper.fromValue(v);
|
||||||
|
}
|
||||||
|
catch (Throwable error) {
|
||||||
|
return MyWrapper.fromError(error);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
上述代码等价于
|
||||||
|
```java
|
||||||
|
erroringFlux.onErrorResume(error -> Mono.just(
|
||||||
|
MyWrapper.fromError(error)
|
||||||
|
));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Catch and rethrow
|
||||||
|
对于捕获异常然后重新抛出的逻辑
|
||||||
|
```java
|
||||||
|
try {
|
||||||
|
return callExternalService(k);
|
||||||
|
}
|
||||||
|
catch (Throwable error) {
|
||||||
|
throw new BusinessException("oops, SLA exceeded", error);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
可以通过`onErrorResume`实现:
|
||||||
|
```java
|
||||||
|
Flux.just("timeout1")
|
||||||
|
.flatMap(k -> callExternalService(k))
|
||||||
|
.onErrorResume(original -> Flux.error(
|
||||||
|
new BusinessException("oops, SLA exceeded", original))
|
||||||
|
);
|
||||||
|
```
|
||||||
|
或者,可以调用`onErrorMap`,其是对`onErrorResume`方法的封装:
|
||||||
|
```java
|
||||||
|
Flux.just("timeout1")
|
||||||
|
.flatMap(k -> callExternalService(k))
|
||||||
|
.onErrorMap(original -> new BusinessException("oops, SLA exceeded", original));
|
||||||
|
```
|
||||||
|
|
||||||
|
#### log and react on the side
|
||||||
|
如果想要实现类似`将异常捕获、打印然后重新抛出`的逻辑,可以使用`doOnError`
|
||||||
|
```java
|
||||||
|
try {
|
||||||
|
return callExternalService(k);
|
||||||
|
}
|
||||||
|
catch (RuntimeException error) {
|
||||||
|
//make a record of the error
|
||||||
|
log("uh oh, falling back, service failed for key " + k);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
上述代码等价于
|
||||||
|
```java
|
||||||
|
LongAdder failureStat = new LongAdder();
|
||||||
|
Flux<String> flux =
|
||||||
|
Flux.just("unknown")
|
||||||
|
.flatMap(k -> callExternalService(k)
|
||||||
|
.doOnError(e -> {
|
||||||
|
failureStat.increment();
|
||||||
|
log("uh oh, falling back, service failed for key " + k);
|
||||||
|
})
|
||||||
|
|
||||||
|
);
|
||||||
|
```
|
||||||
|
##### doOnError
|
||||||
|
`doOnError`和其他以`doOn`为前缀的operators,其通常会被称为`副作用(side effect)`。通过这些operators,可以在不修改sequence的情况下监控chain中的事件。
|
||||||
|
|
||||||
|
|
||||||
|
#### Using resources and the finally block
|
||||||
|
对于`在finally block中清理资源`的行为,可以通过`doFinally`来实现
|
||||||
|
```java
|
||||||
|
Stats stats = new Stats();
|
||||||
|
stats.startTimer();
|
||||||
|
try {
|
||||||
|
doSomethingDangerous();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
stats.stopTimerAndRecordTiming();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### doFinally
|
||||||
|
`doFinally`是无论sequence结束(onError/onComplete)还是取消(cancel),都希望执行的副作用(side effect)。其接收参数类型为`Consumer<SignalType>`,可以通过`signaltype`判断`触发side-effect的terminaction类型`。
|
||||||
|
|
||||||
|
`doFinally`使用示例如下:
|
||||||
|
```java
|
||||||
|
Stats stats = new Stats();
|
||||||
|
LongAdder statsCancel = new LongAdder();
|
||||||
|
|
||||||
|
Flux<String> flux =
|
||||||
|
Flux.just("foo", "bar")
|
||||||
|
.doOnSubscribe(s -> stats.startTimer())
|
||||||
|
.doFinally(type -> {
|
||||||
|
stats.stopTimerAndRecordTiming();
|
||||||
|
if (type == SignalType.CANCEL)
|
||||||
|
statsCancel.increment();
|
||||||
|
})
|
||||||
|
.take(1);
|
||||||
|
```
|
||||||
|
|
||||||
|
对于`try(resource)`的代码,则是可以通过`using`来实现
|
||||||
|
```java
|
||||||
|
try (SomeAutoCloseable disposableInstance = new SomeAutoCloseable()) {
|
||||||
|
return disposableInstance.toString();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##### using
|
||||||
|
`using`代表`Flux由资源派生,并且在Flux处理完成之后都需要对资源执行操作`。
|
||||||
|
```java
|
||||||
|
// resource
|
||||||
|
AtomicBoolean isDisposed = new AtomicBoolean();
|
||||||
|
Disposable disposableInstance = new Disposable() {
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
isDisposed.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DISPOSABLE";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
// using
|
||||||
|
Flux<String> flux =
|
||||||
|
Flux.using(
|
||||||
|
() -> disposableInstance,
|
||||||
|
disposable -> Flux.just(disposable.toString()),
|
||||||
|
Disposable::dispose
|
||||||
|
);
|
||||||
|
```
|
||||||
|
其中,`resource`实现了`Disposable`接口,而`Flux.using`接收的参数类型分别为
|
||||||
|
- `() -> disposableInstance`: resource supplier
|
||||||
|
- `disposable -> Flux.just(disposable.toString())`: 一个factory,根据resource产生publisher
|
||||||
|
- `Disposable::dispose`: resource cleanup
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user