標籤:ide false 字元 div 提示 缺點 解決 ica nbsp
無論是Dubbo還是JSF等RPC架構,一般都會把介面分為2部分:
1,服務端(provider)
2,用戶端(consumer)
由於,用戶端與服務端可能不在同一個應用中,所以用戶端一般在調用服務端的介面時,通常會返回一個結果實體,來標明這一次請求操作是否成功。
例如:
public class BaseResultDto<T> { /** * 是否操作成功 */ private boolean success; /** * 提示資訊 */ private String msg; /** * 操作結果 */ private T result;}
用戶端在拿到這個實體後,可以明確得知,這一次操作是否成功。
但是防禦式編程中,我們應該對一切未知的介面都持有懷疑態度,況且不怕一萬就怕萬一:“如果服務端出現異常怎麼辦?”
網上有2中答案:
1,直接將異常拋出去,經過RPC序列化後,用戶端進行展示。
2,不拋異常出去,服務端進行全方位攔截,攔截到後,通過BaseResultDto,告訴用戶端現在服務端出現異常了。
但是各自的缺點很明顯:
1,服務端與用戶端,很可能不在同一個應用中,所以各自會依賴不同的jar包,比方說:服務端拋出了個spring的duplicateKeyException,但是用戶端並沒用引用spring的相關jar包,這樣就會導致:拋出異常後,由於用戶端沒有依賴這個類,最終拋出個ClassNotDefError,注意是Error不是Exception。如果用戶端只對Exception進行捕獲的話,會導致直接拋到最頂層。可能日誌、重試等都沒了。
2,全方位攔截後,可能返回的結果中只會告訴用戶端:“系統出現異常”,無法準確通過日誌去定位問題。
最終解決方案:
將2者折中處理,服務端全方位進行攔截,如果出現異常後,把異常資訊轉換成字串,然後把異常資訊返回到用戶端中:
public class BaseResultDto<T> {/** * 是否操作成功 */private boolean success;/** * 提示資訊 */private String msg;/** * 操作結果 */private T result;/** * 異常堆棧資訊 */private String errorTrace;}
errorTrace就是儲存異常對戰資訊的屬性,這樣如果用戶端檢測到success為false,這樣就可以直接把errorTrace打到log中,方便定位問題。
使用Dubbo、JSF等RPC架構時,對於異常的處理