一、異常現象
在 JAVA 開發中我們經常會使用RestTemplate進行遠程接口調用,如果請求的接口出現異常:超時、服務不存在等等情況,這時響應狀態不是200,而是400、500等等狀態碼,這種情況下,程序便會拋出異常,如下:
上面出現的異常我是模擬出來的,由「/postss/1」替換了正確的地址由「/posts/1」。這時請求該服務不存在,肯定會拋出404異常。代碼如下:
這裡拋出了404 Not Found 的異常,後面的業務邏輯肯定是無法執行的了。
我們在實際的開發中,不管服務端因為什麼問題導致異常,都應該獲得最終的請求結果(HTTP請求結果狀態400、500),而不是獲得一個拋出的異常。
二、源碼解析-默認實現
首先程序中99%的異常都是可以自定義處理的,RestTemplate請求結果的異常自然也是可以自定義處理的。在開始自定義之前,我們來探究一下異常的默認處理實現,以此來說明為什麼會出現這樣的現象?
RestTemplate請求結果的異常處理器接口是ResponseErrorHandler,下面介紹一下該接口的兩個重要方法:hasError():用於判斷HttpResponse是否是異常響應(通過狀態碼)handleError():用於處理異常響應結果(非200狀態碼段)DefaultResponseErrorHandler是ResponseErrorHandler的默認實現下面是ResponseErrorHandler接口的源碼實現:
上面提到ResponseErrorHandler的默認實現是DefaultResponseErrorHandler,既然如此我們跟蹤一下該實現看看是如何來處理異常響應的?從HttpResponse解析出Http StatusCode,如果狀態碼StatusCode為null,就拋出UnknownHttpStatusCodeException異常。
如果StatusCode存在,就會調用DefaultResponseErrorHandler#handleError(ClientHttpResponse, HttpStatus)接口來解析出StatusCode的series,也就是狀態碼段(除了200段,其他全是異常狀態碼),解析規則是StatusCode/100取整。
進一步針對客戶端異常和服務端異常進行處理,處理的方法是拋出HttpClientErrorException。
三、RestTemplate自定義異常處理
通過上面的介紹可知:要實現RestTemplate自定義異常處理,只需要實現ResponseErrorHandler 接口就可以。方法如下:
將MyRestErrorHandler 在RestTemplate實例化的時候進行註冊,這樣請求的異常處理便會走自定義的異常處理類進行處理了。實現方式如下:
這時再去執行第一小節中的示例代碼,就不會拋出異常。而是得到一個HTTP Status 404的結果。我們可以根據這個結果,在程序中繼續向下執行代碼。
到此已經介紹完RestTemplate請求異常處理邏輯,歡迎大家在評論區踴躍發言,各抒自見,共同交流學習,也歡迎大家對本文中錯誤或者不足之處提出您的寶貴意見!