最近因為疫情導致程序汪在家開啟遠程辦工,晚上開心的寫著業務代碼的時候突然運營妹子找到我說線上出現了一個問題需要幫看看
然後就開啟查bug模式,比較悲劇的是生產環境操作不了程序汪沒權限,於是就根據日誌分析問題
就這麼一個異常,敏感信息我打碼,數據驗證功能很常見
其實解決線上問題 分析日誌是最佳手段,可惜很多開發日誌打的太粗糙
發起人:運營妹子或運維直接找到開發負責人
提供線索:截圖、業務操作場景、日誌等等,有時候日誌需要開發去線上抓
分析:根據提供線索,如通過日誌定位具體異常原因,一般悲劇發生這一環節,日誌看不懂,異常描述模糊
復現問題:在線下環境復現此問題,當然很多時候線下復現不出來
解決手段:定位出問題馬上解決,如代碼發布補丁或開關控制下,程序汪公司開發功能有個習慣對於有風險的功能都有降級開關,可以動態開關的
程式設計師一直都在解決bug的路上,線下環境當然很爽遇到問題都是習慣性的說一句:給我一個斷點,我馬上定位出來 關鍵線上環境是不能debug的哦
java程式設計師非常喜歡debug,大家都懂的,解決問題是真的又快又爽
今天不是來講怎麼debug,這是java程式設計師的基本素質,不會的可以錘一錘自己
先上幾個錯誤日誌例子
一個catch大蓋帽
try {
//代碼邏輯一
//代碼邏輯二
//代碼邏輯三
....
//代碼邏輯十
} catch (Exception e) {
LoggerUtil.error(e, LOGGER, "{0} error.", LOG_NAME);
}
很多程式設計師為了偷懶,用一個 大catch 蓋住所有異常,這是一個非常粗糙的異常處理,程序汪剛工作時很喜歡這樣寫代碼。寫代碼的人是爽了,可是定位線上問題的人就苦逼了。
JAVA的良苦用心,儘量細化你的異常
java運行時異常,RuntimeExecption在java.lang包下提供了大量類
1、ClassCastException(類轉換異常)
2、IndexOutOfBoundsException(數組越界)
3、NullPointerException(空指針,最討厭的異常)
4、ArrayStoreException(數據存儲異常,操作數組時類型不一致)
5、BufferOverflowException異常
等等.
程式設計師看到這些異常名,立刻知道發生了什麼,要的就是這個效果
java提供了大量的運行異常,我們自己的業務異常也像java一樣拼命繼承RuntimeExecption,這樣異常類不就爆炸了嗎
更好的辦法是定義一個運行異常然後通過枚舉去定義具體異常場景,廢話不多說上代碼案例
一個運行異常類
public class BizException extends RuntimeException {
/** 錯誤碼. */
private ErrorCodeEnum errorCode;
/** 詳細錯誤信息 */
private Map<String, String> errorMap = new HashMap<String, String>();
/**
* 帶參構造器.
* @param errorCode
*/
public BizException(ErrorCodeEnum errorCode) {
super(errorCode.getDesc());
this.setErrorCode(errorCode);
}
/**
* 帶參構造器.
* @param errorCode
* @param message
*/
public BizException(KbErrorCodeEnum errorCode, String message) {
super(StringUtils.isNotBlank(message) ? message : errorCode.getDesc());
this.setErrorCode(errorCode);
}
一個枚舉,用來定義具體錯誤碼
public enum ErrorCodeEnum {
SYS_ERROR("SYS_ERROR", "系統錯誤,請重試"),
ILLEGAL_ARGS("ILLEGAL_ARGS", "參數校驗錯誤"),
具體業務異常的錯誤碼一定要定義足夠詳細
錯誤例子 查詢失敗
QUERY_FAIL("QUERY_FAIL", "查詢失敗"),
正確例子 電影詳細查詢失敗,如果業務非常複雜可以繼續詳細此枚舉值
MOVIE_DETAIL_QUERY_FAIL("MOVIE_DETAIL_QUERY_FAIL", "電影詳細查詢失敗"),
一個複雜業務的數據驗證可能有上百的錯誤碼枚舉值,
越具體越好,線上出現bug可以第一時間快速地位到具體模塊具體功能的甚至具體代碼,這樣就完美了
程序汪上次犯的錯誤就是異常碼定義了,但是多處異常代碼公用一個異常碼導致不能快速定位是那裡出了異常,只能通過分析整個邏輯代碼來判斷bug原因
下面偽代碼比上面異常一個catch處理就優秀多了,不足的是3處邏輯異常碼是一樣的
try {
//代碼邏輯一
throw new BizException(MOVIE_DETAIL_QUERY_FAIL);
//代碼邏輯二
throw new BizException(MOVIE_DETAIL_QUERY_FAIL);
//代碼邏輯三
throw new BizException(MOVIE_DETAIL_QUERY_FAIL);
}
catch (BizException e) {
LoggerUtil.error(e, LOGGER, "{0} error.", LOG_NAME);
}
catch (Exception e) {
LoggerUtil.error(e, LOGGER, "{0} error.", LOG_NAME);
}
不要用一個catch蓋所有異常
採用自定義異常+錯誤碼枚舉 的優雅方式
錯誤碼枚舉請定義足夠詳細
歡迎留言回復,你項目中異常處理是怎麼設計的
異常推薦文章
spring的全局自定義異常案例「完美攔截Controller層全部異常」
java開發中異常怎麼定義好 程式設計師:不知道
Java 處理異常 9 個最佳實踐,你知道幾個?