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

Servlet 異常處理全攻略:聲明式配置與程式化捕獲實戰

     編輯:Java 綜合教學

Servlet 異常處理全攻略:聲明式配置與程式化捕獲實戰

為了提供友好的用戶體驗,生產環境絕不能讓堆疊追蹤直接暴露給瀏覽器。Servlet 規範提供了兩種互補的異常處理機制:聲明式(web.xml 配置)與程式化。本文通過完整範例演示如何處理 HTTP 錯誤碼(404、500)與 Java 異常類別,並展示如何用 Servlet 統一輸出錯誤頁面。

一、聲明式異常處理:web.xml <error-page>

在 web.xml 中透過 <error-page> 元素映射錯誤碼或異常類別到處理資源(靜態 HTML、JSP 或 Servlet)。

1. 子元素說明

  • <error-code>:HTTP 狀態碼(如 404、500)。
  • <exception-type>:Java 異常全限定名(如 java.io.FileNotFoundException)。
  • <location>:處理資源路徑(以 / 開頭,相對於 Web 應用根目錄)。

2. 範例一:處理 404 錯誤 → 靜態 HTML

FileNotFound.html

<html>
<head><meta charset="UTF-8"><title>頁面未找到</title></head>
<body>
你訪問的頁面並不存在,或已被移動。<p>
如有問題請聯繫 <a href="#">管理員</a>
</body>
</html>

web.xml

<error-page>
    <error-code>404</error-code>
    <location>/FileNotFound.html</location>
</error-page>

訪問不存在路徑(如 /index1.jsp),容器自動轉發到該 HTML。

404靜態頁面效果

3. 範例二:處理 404/401 → 動態 Servlet

當錯誤頁面需包含動態邏輯(記錄日誌、查詢資料庫、國際化)時,用 Servlet 處理更靈活。

ErrorHandlerServlet


public class ErrorHandlerServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("text/html;charset=gb2312");
        PrintWriter out = resp.getWriter();
        Integer statusCode = (Integer) req.getAttribute("javax.servlet.error.status_code");
        
        out.println("<html><head><title>錯誤列表</title></head><body>");
        switch (statusCode) {
            case 401:
                out.println("<h2>HTTP 錯誤碼:" + statusCode + "</h2>");
                out.println("你未被授權訪問此資源。");
                break;
            case 404:
                out.println("<h2>HTTP 錯誤碼:" + statusCode + "</h2>");
                out.println("頁面不存在或已移動。");
                break;
        }
        out.println("如有問題請聯繫 <a href='#'>管理員</a>");
        out.println("</body></html>");
        out.close();
    }
}

web.xml


<servlet>
    <servlet-name>ErrorHandlerServlet</servlet-name>
    <servlet-class>com.lp.servlet.ErrorHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ErrorHandlerServlet</servlet-name>
    <url-pattern>/errorHandler</url-pattern>
</servlet-mapping>

<error-page>
    <error-code>404</error-code>
    <location>/errorHandler</location>
</error-page>
<error-page>
    <error-code>401</error-code>
    <location>/errorHandler</location>
</error-page>

容器會將錯誤屬性(javax.servlet.error.status_code、javax.servlet.error.exception 等)放入 request 屬性,Servlet 可取出動態生成頁面。

動態錯誤頁面效果

4. 範例三:處理特定 Java 異常 → ExceptionHandlerServlet

拋出異常的 Servlet


public class FileExceptionServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws FileNotFoundException {
        File file = new File("1.txt"); // 故意不存在
        new FileInputStream(file);     // 拋出 FileNotFoundException
    }
}

異常處理 Servlet


public class ExceptionHandlerServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("text/html;charset=gb2312");
        PrintWriter out = resp.getWriter();
        out.println("<html><head><title>錯誤</title></head><body>");
        out.println("應用程式出錯:伺服器端檔案可能被刪除。");
        out.println("請聯繫 <a href='#'>管理員</a>");
        out.println("</body></html>");
        out.close();
    }
}

web.xml


<servlet>
    <servlet-name>ExceptionHandlerServlet</servlet-name>
    <servlet-class>com.lp.servlet.ExceptionHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ExceptionHandlerServlet</servlet-name>
    <url-pattern>/exceptionHandler</url-pattern>
</servlet-mapping>

<error-page>
    <exception-type>java.io.FileNotFoundException</exception-type>
    <location>/exceptionHandler</location>
</error-page>

直接訪問 /exceptionHandler 觸發異常,容器捕獲並轉發到處理 Servlet。

異常處理效果

二、程式化異常處理:try-catch + sendError

在業務邏輯中主動捕獲異常,記錄日誌,並呼叫 response.sendError(statusCode, message) 觸發容器錯誤頁面機制(可配合聲明式 error-page 顯示友好頁面)。


@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    try {
        File file = new File("1.txt");
        new FileInputStream(file); // 可能拋出 FileNotFoundException
    } catch (FileNotFoundException e) {
        getServletContext().log(e.getMessage()); // 記錄到伺服器日誌
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "檔案未找到");
    }
}

關鍵點:

  • sendError 會提交回應,後續不可再寫入輸出流。
  • 若 web.xml 配置了對應 error-code (500) 的 error-page,容器會顯示該頁面;否則顯示容器預設錯誤頁。
  • 日誌記錄建議用成熟框架(Log4j2、SLF4J),而非 ServletContext.log。

程式化處理效果

三、最佳實踐總結

場景推薦方式說明
全站通用 HTTP 錯誤 (404, 500)聲明式 + 專用錯誤 Servlet集中維護,支援國際化、動態佈局
特定業務異常 (如檔案不存在、業務規則違反)程式化 try-catch + sendError / 自定義異常頁可記錄詳細上下文,決定是否回滾事務
未捕獲的 RuntimeException聲明式 exception-type=java.lang.Throwable (放最後)作為最後防線,避免堆疊洩露

掌握這兩種機制的配合使用,能構建健壯、用戶友好的 Web 應用。現代框架(Spring MVC @ControllerAdvice、Spring Boot /error 端點)本質上是對此的進一步封裝,理解原理有助於排查框架層面的異常處理問題。

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