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

Java Web 錯誤/異常頁面統一處理最佳實踐

     編輯:Java 相關知識

默認行為與痛點

Servlet 容器(Tomcat/Jetty)默認拋出 500/404 等錯誤時,顯示容器自帶的醜陋堆棧頁面,洩露服務器信息,用戶體驗極差,且無法記錄完整上下文便於排查。

web.xml 聲明式配置(Servlet 2.5+)

<error-page>
  <error-code>404</error-code>
  <location>/WEB-INF/views/error/404.jsp</location>
</error-page>
<error-page>
  <error-code>500</error-code>
  <location>/WEB-INF/views/error/500.jsp</location>
</error-page>
<error-page>
  <exception-type>java.lang.Exception</exception-type>
  <location>/WEB-INF/views/error/500.jsp</location>
</error-page>
  • error-code:匹配 HTTP 狀態碼。
  • exception-type:匹配異常類型(含子類),優先級高於 error-code。
  • location:必須以 / 開頭,建議放在 WEB-INF 下防止直接訪問。

錯誤頁面獲取異常信息

在錯誤 JSP 中,容器自動設置以下請求屬性(可通過 ${requestScope['key']} 或 request.getAttribute() 獲取):

屬性鍵說明
javax.servlet.error.status_codeHTTP 狀態碼 (Integer)
javax.servlet.error.exception_type異常類名 (Class)
javax.servlet.error.message異常消息 (String)
javax.servlet.error.exception異常對象 (Throwable)
javax.servlet.error.request_uri出錯請求 URI (String)
javax.servlet.error.servlet_name出錯 Servlet 名稱 (String)

通用錯誤頁面模板 (error.jsp)

<%@ page pageEncoding="UTF-8" isErrorPage="true" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
  <title>系統錯誤</title>
  <style>body{font-family: sans-serif; max-width: 800px; margin: 2rem auto; padding: 1rem;} pre{background:#f5f5f5; padding:1rem; overflow:auto;}</style>
</head>
<body>
  <h1>抱歉,系統發生錯誤</h1>
  <p>狀態碼:${requestScope['javax.servlet.error.status_code']}</p>
  <p>異常類型:${requestScope['javax.servlet.error.exception_type']}</p>
  <p>異常信息:${requestScope['javax.servlet.error.message']}</p>
  <p>請求路徑:${requestScope['javax.servlet.error.request_uri']}</p>

  <c:if test="${not empty requestScope['javax.servlet.error.exception']}">
    <h3>堆棧跟蹤</h3>
    <pre>${requestScope['javax.servlet.error.exception'].stackTrace}</pre>
  </c:if>

  <p><a href="${pageContext.request.contextPath}">返回首頁</a> | <a href="javascript:history.back()">上一頁</a></p>
</body>
</html>

進階:統一異常處理類 (Spring MVC / Servlet 3.0+)

Spring MVC 推薦使用 @ControllerAdvice + @ExceptionHandler 實現全局異常處理,返回 JSON 或視圖,避免 web.xml 配置分散:

@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(HttpServletRequest request, Exception ex) {
        log.error("請求 {} 發生異常", request.getRequestURI(), ex);
        ModelAndView mv = new ModelAndView("error/500");
        mv.addObject("exception", ex);
        mv.addObject("url", request.getRequestURI());
        return mv;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public ModelAndView handle404(HttpServletRequest request) {
        return new ModelAndView("error/404");
    }
}

異常信息持久化與告警

  • 在 GlobalExceptionHandler 或錯誤 JSP 中,將異常信息(堆棧、請求參數、用戶 ID、時間戳)寫入日誌文件/數據庫/ELK。
  • 集成 Sentry、SkyWalking、Prometheus Alertmanager 實現實時告警。

Cookie 被禁用時的 Session 追蹤 (URL Rewriting)

若用戶禁用 Cookie,容器無法透過 JSESSIONID Cookie 識別 Session。解決方案:對所有輸出 URL 執行 response.encodeURL() / encodeRedirectURL(),自動附加 ;jsessionid=xxx。

<a href="<%= response.encodeURL("/shop/cart") %>">購物車</a>
response.sendRedirect(response.encodeRedirectURL("/login"));

總結清單

  1. 配置 web.xml 或 @ControllerAdvice 覆蓋 404/500/異常類型。
  2. 錯誤頁面友好提示用戶,開發模式顯示堆棧,生產模式隱藏細節記錄日誌。
  3. 統一異常入口,結合日誌框架(Logback/Log4j2)輸出結構化日誌。
  4. 異常信息入庫/推送告警,縮短 MTTR。
  5. 處理無 Cookie 場景,確保 Session 追蹤不中斷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved