簡體   English   中英

如何處理反應式 Spring webflux 中的錯誤

[英]How to handle errors in Reactive Spring webflux

由於有許多方法,如 onErrorReturn、onErrorResume 等,那么哪個是正確的方法來處理 mono 和通量的反應式 Spring webflux 中的錯誤?

分享我的知識:

總共提供了六種處理錯誤的方法,下面討論五種:

  • onErrorReturn : 返回整個 stream (mono/flux) 的后備值。 例如,如果有 10 個元素的通量,並且元素 3 發生錯誤,則不會執行 rest 4,5,6...,而是會考慮回退值。

  • onErrorResume : 返回整個 stream (mono/flux) 的 Mono/Flux 的后備值。 例如,如果有 10 個元素的通量,並且元素 3 發生錯誤,則不會執行 rest 4,5,6...,而是會考慮回退值。

  • onErrorContinue : 消耗 (error,data) 並且不將其拆分。 它為錯誤元素考慮消費者,並為良好元素保留下游鏈。 例如,如果有 10 個元素的通量,並且元素 3 發生錯誤,則除 3 之外的所有元素(1 到 10)都將正常執行,但元素 3 將具有不同的執行,如 onErrorContinue 的使用者中所述

  • doOnError :消耗錯誤並將其溢出。 停止執行 stream 中的其他元素。

  • onErrorMap :將一個錯誤轉換為另一個錯誤。 停止執行 stream 中的其他元素。

所有這五種方法都有 3 種變體,

  • 簡單:直接考慮預期的參數
  • 有異常:考慮預期參數,如果異常與提供的異常 class 匹配
  • 使用謂詞:如果謂詞產生真,則考慮預期的參數

例子:

  1. onErrorReturn:返回后備值
@Test
public void onErrorReturnDirectly_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorReturn(4)
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void onErrorReturnIfArithmeticException_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorReturn(ArithmeticException.class, 4)
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void onErrorReturnIfPredicatePasses_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorReturn(error -> error instanceof ArithmeticException, 4)
        .subscribe(num -> log.info("Number: {}", num ));
}
  1. onErrorResume:以 Mono/Flux 的形式返回后備值
@Test
public void onErrorResume_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorResume(error -> Mono.just(4))
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void onErrorResumeIfArithmeticException_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorResume(
            ArithmeticException.class,
            error -> Mono.just(4)
        )
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void onErrorResumeIfPredicatePasses_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorResume(
            error -> error instanceof ArithmeticException,
            error -> Mono.just(4)
        )
        .subscribe(num -> log.info("Number: {}", num ));
}
  1. onErrorContinue:消耗(錯誤,數據)並且不將其拆分。
@Test
public void onErrorContinue_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorContinue((error, obj) -> log.info("error:[{}], obj:[{}]", error, obj ))
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void onErrorContinueIfArithmeticException_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorContinue(
            ArithmeticException.class,
            (error, obj) -> log.info("error:[{}], obj:[{}]", error, obj )
        )
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void onErrorContinueIfPredicatePasses_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorContinue(
            error -> error instanceof ArithmeticException,
            (error, obj) -> log.info("error:[{}], obj:[{}]", error, obj )
        )
        .subscribe(num -> log.info("Number: {}", num ));
}
  1. doOnError:消耗錯誤並將其溢出
@Test
public void doOnError_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .doOnError(error -> log.info("caught error"))
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void doOnErrorIfArithmeticException_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .doOnError(
            ArithmeticException.class,
            error -> log.info("caught error")
        )
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void doOnErrorIfPredicatePasses_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .doOnError(
            error -> error instanceof ArithmeticException,
            error -> log.info("caught error")
        )
        .subscribe(num -> log.info("Number: {}", num ));
}
  1. onErrorMap:將一個錯誤轉換為另一個錯誤
@Test
public void OnErrorMap_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorMap(error -> new RuntimeException("SomeMathException"))
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void OnErrorMapIfArithmeticException_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorMap(
            ArithmeticException.class,
            error -> new RuntimeException("SomeMathException")
        )
        .subscribe(num -> log.info("Number: {}", num ));
}

@Test
public void OnErrorMapIfPredicatePasses_Mono() {
    Mono.just(2)
        .map(i -> i/0) // will produce ArithmeticException
        .onErrorMap(
            error -> error instanceof ArithmeticException,
            error -> new RuntimeException("SomeMathException")
        )
        .subscribe(num -> log.info("Number: {}", num ));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM