前沿拓展:
初識(shí)響應(yīng)式編程的時(shí)候,除了從命令式的思維方式轉(zhuǎn)變?yōu)楹瘮?shù)式的編程方式外,其中有一個(gè)很大的不適應(yīng)的地方就是在面對(duì)異常時(shí)該怎么處理,尤其是面對(duì)檢查異常(Checked Exception)時(shí)更是不知所措。在遇到異常時(shí),我們通用的處理方式就是打日志、降級(jí)兜底、重試三板斧,本文通過Project Reactor的文檔以及源碼來深入解讀,在reactor中是如何優(yōu)雅地實(shí)現(xiàn)這異常處理三板斧。
在介紹怎么使用前,我們先回顧下在用reactor編程的時(shí)候,遇到的幾個(gè)問題:
遇到異常時(shí),如果能處理,我該怎么兜底/降級(jí)遇到無法處理的異常時(shí),我該怎么打印日志,并往外拋遇到聲明了檢查異常的方法時(shí),該怎么處理如果調(diào)用失敗了(如請(qǐng)求超時(shí)),該如何重試如果出現(xiàn)異常了,流里面的后續(xù)數(shù)據(jù)還會(huì)繼續(xù)發(fā)送嗎異常處理的底層機(jī)制
在回答這些問題,就需要我們第一對(duì)reactor處理異常的機(jī)制要有理解。先說結(jié)論,如文檔上說的:
Before you learn about error-handling operators, you must keep in mind that any error in a reactive sequence is a terminal event. Even if an error-handling operator is used, it does not let the original sequence continue. Rather, it converts the 與命令式編程有throws關(guān)鍵字聲明不同,reactor中處理檢查異常都必須用try-catch來處理,處理的方式有以下三種:
捕獲到異常并從中恢復(fù)。序列繼續(xù)正常的進(jìn)行。捕獲異常,將其封裝成一個(gè) 不檢查 的異常,第二將其拋出(中斷序列)。如果你需要返回一個(gè) Flux(例如,在 flatMap 中),那么就用一個(gè)產(chǎn)生錯(cuò)誤的 Flux 來封裝異常,如下所示:return Flux.error(checkedException)。(這個(gè)序列也會(huì)終止。)
這三種方式中,其中最常見也最常用的方式就是第二種,將檢查異常轉(zhuǎn)化為非檢查異常,如throw new RuntimeException(e)。但是reactor提供了輔助工具類Exceptions,進(jìn)而可以相對(duì)優(yōu)雅簡潔的進(jìn)行統(tǒng)一處理。如以下這個(gè)例子
public String convert(int i) throws IOException {
if (i > 3) {
throw new IOException("boom " + i);
}
return "OK " + i;
}
Flux<String> 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");
}
}
);
由于convert聲明了檢查異常IOException,所以必須要try-catch住,再利用Exceptions.propagate來封裝為非檢查異常。相比于直接用throw new RuntimeException(e),利用Exceptions的好處在onError處理階段可以用Exceptions.unwrap()方法來獲取內(nèi)部真實(shí)拋出的異常,體現(xiàn)了利用工具類的好處——簡潔明了。
小編綜合來說
本文先從reactor異常處理的底層機(jī)制講起,講清楚了一個(gè)基本概念:只要出現(xiàn)異常,不管如何處理,舊的流都已經(jīng)結(jié)束,接下來處理的都是新的流。在這基礎(chǔ)上,按命令式編程中的try-catch-finally的方式,用reactor的方式進(jìn)行了一一替代介紹,希望通過對(duì)比的方式,能更好的掌握在reactor中如何優(yōu)雅的處理異常。
拓展知識(shí):
原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請(qǐng)注明出處:http://m.xiesong.cn/122673.html