異常處理和日誌輸出使用小結
1、能通過預檢查的異常直接處理,不用catch來處理,無法通過預檢查的異常才去使用catch處理;
2、不要對大段代碼進行try catch,只需要在非穩定代碼地方進行try catch處理;
3、異常的捕獲是為了處理他而不是拋棄它,如果不想處理可以傳給外層的調用者,但是應用的最外層調用者必須處理它。通常在SpringMVC應用中,controller就已經是最外層的調用者了,異常最遲在這裏就必須處理掉而不能將異常拋給前端,返回給前端的必須是一個處理之後的比較友好的提示信息,通常異常是在controller層或者Service層就處理掉;
4、捕獲到異常時,通常做法是先將異常的詳細信息輸出到日誌,然後再給前端返回一個比較友好的提示信息,這樣在前端獲取到異常結果時可以通過日誌系統快速定位到問題所在,但是通常情況下日誌會比較多,日誌中定位問題比較困難,有以下兩個建議:
2)、在輸出日誌時生成一個異常唯一編碼輸出到日誌中,同時在返回給調用者的信息中帶上這個編碼,這樣在前端捕獲到異常結果時能根據這個異常唯一編碼快速定位到日誌對應地方;]
5、通常要捕獲的異常的地方有:方法入口處進行參數為空和參數合法性檢查,對框架或者JDK等底層代碼拋出的異常(比如iBatis拋出的數據庫操作異常、Spring框架拋出的異常、RPC調用拋出的異常、網絡操作拋出的異常、除零、空指針、下標越界等JDK拋出的異常等等),業務操作異常(比如查詢數據返回結果為空、數據業務合法性檢查等等);其中業務操作異常建議根據業務情況做一個匯編,將每種異常分配一個統一的編碼和描述信息定義為一個枚舉值,這樣方便業務異常的排查;
6、一定不要忘記對資源對象、流對象在try finally中關閉,並且還要做異常處理;JDK7及以上的建議使用try-with-resources的方式處理,代碼看起來會簡潔很多;
7、不能在finally中使用return,因為這會導致try中的return失效;
8、調用其他方法必須進行空指針判斷(註意基本數據類型和基本數據類型對象,比如int和Integer,Integer有可能為NULL,而int不可能為NULL,還有級聯調用也容易產生空指針異常,比如:obj.getA().getB().getC());
9、對於trace/debug/info級別的日誌輸出,必須使用條件輸出或者占位符的方式,避免執行字符串拼接而浪費系統資源,但是日誌最終卻沒有打印;
錯誤:logger.debug("process trade with id:" + id + "and symbol:" + symbol);
正確:
條件輸出:
if (logger.isDebugEnabled()) {
logger.debug("process trade with id:" + id + "and symbol:" + symbol);
}
占位符:
logger.debug("process trade with id: {} and symbol: {}", id, symbol);
10、謹慎的註意每條日誌輸出的級別設置:debug級別的日誌用於協助調試用的,一般只輸出到開發環境和測試環境嗎,info級別的日誌必須有選擇的輸出,其作用是用於協助查看系統運行狀況;debug和info級別的日誌嚴禁在生產環境輸出;warn級別的日誌用於非系統和業務錯誤,但是會影響系統輸出結果的信息,比如記錄用戶輸入參數錯誤的情況可以使用warn級別日誌,避免用戶投訴時有據可依;error級別只記錄系統邏輯錯誤、異常等重要的錯誤信息,如非必要,請不要使用這個級別;
異常處理和日誌輸出使用小結