首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

J2EE 異常框架設計:責任分層、Checked/Unchecked 劃分與最佳實踐

     編輯:Java 程式設計入門

異常體系速覽

Throwable
├── Error              // JVM 責任:動態連結失敗、虛擬機錯誤 → 應用不捕獲
└── Exception
    ├── RuntimeException   // 程式邏輯錯誤責任:NPE、越界、非法參數 → 應用修代碼不捕獲
    └── (其他)             // Checked Exception:具體應用責任 → 必須聲明/捕獲/處理

核心原則:絕不向客戶端暴露 RuntimeException/Error——它們不屬於客戶解決範疇。

分層異常處理架構

1. 業務層:包裝 Checked Exception

public class BusinessException extends ApplicationException {
    public BusinessException(String msg) { super(msg); }
    public BusinessException(String msg, Throwable cause) { super(msg, cause); }
}

public class ApplicationException extends Exception {
    private Throwable cause;
    // 構造器、initCause、getCause
    // 重寫 getMessage() 遞歸拼接原因鏈訊息
    // 重寫 printStackTrace() 遞歸打印 "Caused by:" 鏈
}

2. 業務方法:捕獲具體異常 → 轉換為 BusinessException

public void doBusiness() throws BusinessException {
    try {
        execute1(); // 可能拋 SQLException
        execute2(); // 可能拋 IOException
    }
    catch (SQLException e) { throw new BusinessException("DB error", e); }
    catch (IOException e) { throw new BusinessException("IO error", e); }
    // 關鍵:若捕獲 Exception 必須過濾 RuntimeException!
    catch (Exception e) {
        if (!(e instanceof RuntimeException))
            throw new BusinessException(e);
        // RuntimeException 直接向上拋,不包裝
        throw (RuntimeException) e;
    }
}

3. 表現層:統一攔截與轉換

// Struts Action 範例
public void doAction(...) {
    try {
        businessService.doBusiness();
    }
    catch (Exception e) {
        if (e instanceof RuntimeException) {
            // 記錄錯誤、通知開發人員、返回友好錯誤頁
            log.error("Program bug!", e);
            notifyDeveloper(e);
            return "systemError";
        }
        else {
            // Checked Exception (BusinessException 等) → 返回業務錯誤頁
            request.setAttribute("errorMsg", e.getMessage());
            return "businessError";
        }
    }
}

ApplicationException 關鍵實現細節

  • 原因鏈保留:構造器接受 Throwable cause,initCause() 兼容 JDK 1.4+
  • 訊息聚合:getMessage() 遞歸拼接 "msg: causeMsg: causeCauseMsg..."
  • 堆疊追蹤完整:printStackTrace() 遞歸打印 "Caused by: ...",支援 PrintStream/PrintWriter 重載
  • 不處理 RuntimeException:getMessage() 遇到 ApplicationException 子類停止遞歸,避免混入程式錯誤

架構優勢

層級職責異常類型
資料存取拋出具體 Checked Exception (SQLException 等)Checked
業務邏輯捕獲具體 → 包裝為 BusinessExceptionChecked
表現/控制攔截 BusinessException → 用戶友好提示;攔截 RuntimeException → 記錄/告警/系統錯誤頁Checked / Unchecked 分流
客戶端僅見業務錯誤碼/訊息,零技術細節—

常見錯誤與修正

❌ catch (Exception e) { throw new BusinessException(e); }
→ 吞沒 RuntimeException,導致程式 Bug 偽裝成業務錯誤,開發者無感知

✅ catch (Exception e) { if (!(e instanceof RuntimeException)) throw new BusinessException(e); throw (RuntimeException)e; }
→ 分流處理,RuntimeException 保持原樣向上傳播

總結

  1. 異常分兩類:Checked(應用責任)、Unchecked(JVM/程式責任)
  2. 應用自定義異常繼承 Exception,歸屬 Checked
  3. 每層包裝時過濾 RuntimeException,不可混入
  4. 表現層分流處理:業務錯誤給用戶,程式錯誤給開發者
  5. 保留完整原因鏈,支援診斷排查

這套框架將「責任歸屬」內建於異常體系,讓錯誤處理從雜亂無章變為清晰可控的工程實踐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved