在生產環境中,異常處理不僅關乎代碼正確性,更直接影響用戶體驗與運維效率。理想的企業級異常處理應達成:
原則 1 與 3 看似衝突,實則需平衡:在不丟失原始異常意圖的前提下,盡可能靠近拋出點捕獲。
System.out.println 存在嚴重缺陷:
解決方案:使用聲明式日誌框架 (如 Log4J),實現零開銷關閉、分級記錄、多輸出目標。
| 類別 | 包含 | 容器行為 | 適用場景 |
|---|---|---|---|
| 系統異常 | RuntimeException、Error 及其子類 |
交易回滾、Bean 實例銷毀、記錄日誌、拋給客戶端 RemoteException |
資料庫連線失效、配置錯誤、不可預期的系統故障 |
| 應用異常 | 繼承 Exception (非 RuntimeException) 的自訂異常 |
交易不自動回滾、Bean 實例保留、原樣拋給客戶端 | 業務規則違反 (如餘額不足)、輸入驗證失敗、可預期的業務流程中斷 |
ejbCreate/ejbFind 拋出應用異常 → 交易回滾setRollbackOnly)// 錯誤做法
try { ... } catch (Exception e) { throw new MyAppException(e); }
問題:丟失原始異常類型,客戶端無法區分業務錯誤與系統故障。
改進:保留原始異常鏈,僅包裝需轉換語義的異常。
// 錯誤做法
finally { try { conn.close(); } catch (SQLException ignore) {} }
改進:記錄清理失敗日誌,或使用 try-with-resources (Java 7+)。
public class AppException extends Exception {
private final String errorCode;
private final Object[] params; // 國際化參數
public AppException(String errorCode, String msg, Throwable cause) {
super(msg, cause);
this.errorCode = errorCode;
}
// getters...
}
建立統一錯誤碼註冊表 (如 ERR-1001: InsufficientBalance),前後端共用,支援國際化訊息模板。
卓越的 EJB 異常處理建立在:清晰的異常分類、聲明式日誌框架、容器契約的深度理解、統一的錯誤碼體系 之上。投資於異常處理基礎設施,將在系統全生命週期中大幅降低故障排查成本。