異常要怎麼拋?

上一章,我們一起學習了打日誌的點點滴滴,很多同學跟我反饋,自己好像從來沒打對過日誌,也有同學跟我吐槽,MD,最討厭那些吞異常的SX。

今天,我們就來看看這個有意思的問題: 異常到底該怎麼拋?

今天,我依然在地鐵上與你分享,加班🐶,傷不起。﹏。

講解異常之前,我們先看另外一個問題: http的狀態碼有哪些?

這個我相信大家都很熟悉了,我隨便說幾個:

200,成功

400,錯誤的請求

401,未認證

403,未授權

500,服務器內部錯誤

503,網關錯誤

嗯,知道這麼幾個就差不多了,其中,401和403,一個表示未認證,一個表示未授權,未認證可以理解爲沒有登錄的意思,未授權可以理解爲沒有權限,有可能是沒登錄沒有權限,也有可能是登錄但是你就是沒有權限,這不是本文的重點,仔細體會一下就好。

我們主要來看400和500這兩個狀態碼,400表示錯誤的請求,500表示內部服務器錯誤,他們有什麼本質的區別麼?

用一句話來解釋,一個表示因爲客戶端的參數不對導致服務器無法繼續處理引起的錯誤,一個表示服務器內部的某些因素導致的錯誤,這裏的某些因素可能是代碼問題,數據庫問題,遠程調用問題,等等。

對於400錯誤,我們一般自己檢查下請求參數就可以給用戶友好的提示,比如,新增用戶卻沒有填寫用戶名,我們直接提示用戶名不能爲空就好了。

對於500錯誤,它是服務器內部的錯誤,比如你的代碼空指針了,數據庫用戶名這個字段長度不夠,A調B,B卻不通,等等,這種異常你怎麼給用戶提示呢?沒法提示,不能直接把異常堆棧給用戶吧(有沒有中招😁)

好吧,這下真的用一句話來總結,400是用戶的錯誤,500是程序員的錯誤,啊哈哈。

針對這兩種錯誤呢,我們使用spring框架一般都會做統一的異常處理層。

比如說,我的新項目,我分別定義了兩個異常類,BadRequestException和SeverErrorException,然後在spring異常層判斷如果是BadRequestException我就直接返回msg,如果是SeverErrorException我就全部返回"內部服務器錯誤"。

本以爲,大家都按我這個來用就好了,結果,轉測之後,測試天天在羣裏喊,咋回事啊,怎麼全都是"內部服務器錯誤",快點幫我查一下。

我,握了棵草,查看了幾個人的代碼之後,我發現,全部在亂用,被逼無奈之下,我讓他們都改一下,然後每個人都問我一下,爲什麼不能用這個卻要用那個,前面幾個我還能耐心的給講講細節,後面我實在不耐煩了,最後,亮出了我的大招。

我在common中把ServerErrorException移到了與異常處理類同包下,並把其可見性改成了包包內可見,然後,對所有人說你們只能使用BadRequestException,ServerErrorException只能我在框架層使用,算是徹底解決了這個問題。

寫了這麼多,好像還沒有講到今天的主題: 異常怎麼拋的問題。

其實,對於業務開發者,真正能使用到的就應該是隻有對於客戶端錯誤的檢查自己手動拋出異常,其他的異常一律不需要關心,比如空指針異常,遠程調用異常,數據庫異常,你要相信,這些異常都會在框架層處理的很好。

不需要在你的代碼起止加try catch!

不需要在你的代碼起止加try catch!

不需要在你的代碼起止加try catch!

當然,受檢異常除外,什麼是受檢異常的,簡單點講,就是非運行時異常,比如,讀取文件,有可能拋出FileNotExistException,這類異常需要你手動捕獲異常,在編譯期就需要try catch,但是,即使這樣,你也應該保證你的try catch範圍足夠小,只包住那一個方法調用即可,並且,在catch中包裝成你自己的運行時異常繼續往外拋。

咦,這裏就可能會出現開頭說的吞異常的問題了,所以說try catch一定要按下面的格式寫:

try {

} catch (XxxException e) {
throw new YourRuntimeException("xxx文件不存在",e);
}

注意,這裏不需要打印日誌,直接帶上e往外拋就好了。

如果不帶e,就變成吞異常了。

最後,爲什麼500不能隨便拋呢?

正常來說,很多大公司都會監控http返回碼,如果是500是要告警的,發郵件發短信,半夜把程序員(你)叫起來去改問題的,有可能還會通報批評,很嚴重的!

好了,今天就先到這裏,你們公司是怎麼定義異常,怎麼規範拋異常的呢?歡迎留言討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章