JSP 异常处理

page 指令的 errorPage、isErrorPage、web.xml 全局错误页、以及日志。

Intermediate
Key Points页面级用 errorPage 指定错误页,应用级用 web.xml 的 error-page;错误页标 isErrorPage=true 才能拿 exception。

页面级

JSP
<%-- business.jsp:本页出错就去 500.jsp --%>
<%@ page contentType="text/html;charset=UTF-8"
         errorPage="/WEB-INF/errors/500.jsp" %>
<%
    int n = Integer.parseInt(request.getParameter("n"));
%>
JSP
<%-- 500.jsp:我是错误页 --%>
<%@ page isErrorPage="true" contentType="text/html;charset=UTF-8" %>
<!DOCTYPE html>
<html><body>
<h1>页面出错了</h1>
<p><%= exception.getClass().getSimpleName() %>: <%= exception.getMessage() %></p>
</body></html>

A relative errorPage path is resolved against the current page; a leading / means the application root. Keeping it under WEB-INF stops users from opening the error page directly.

应用级

XML
<error-page>
  <error-code>404</error-code>
  <location>/WEB-INF/errors/404.jsp</location>
</error-page>
<error-page>
  <error-code>500</error-code>
  <location>/WEB-INF/errors/500.jsp</location>
</error-page>
<error-page>
  <exception-type>java.lang.NumberFormatException</exception-type>
  <location>/WEB-INF/errors/bad-param.jsp</location>
</error-page>

Page-level config affects one page; application-level catches everything unhandled. Real projects use both: a global safety net plus finer control on specific pages.

错误页能拿到什么

JSP
<%@ page isErrorPage="true" contentType="text/html;charset=UTF-8" %>
<%
    Object status = request.getAttribute("jakarta.servlet.error.status_code");
    Object msg    = request.getAttribute("jakarta.servlet.error.message");
    Object uri    = request.getAttribute("jakarta.servlet.error.request_uri");
    Throwable ex  = (Throwable) request.getAttribute("jakarta.servlet.error.exception");

    if (ex != null) {
        // 只写日志,不输出到页面
        getServletContext().log("页面异常: " + uri, ex);
    }
%>
<!DOCTYPE html>
<html><body>
<h1>出错了</h1>
<p>错误编号:<%= status %></p>
<p><a href="<%= request.getContextPath() %>/">返回首页</a></p>
</body></html>
Printing exception.printStackTrace(response.getWriter()) exposes class names, package layout, SQL and file paths to users. Show an id and a friendly message; keep details in the log.

try-catch 还是抛出去

SituationHandle where
参数格式错本页 try/catch + sendError(400)
资源不存在本页 sendError(404)
数据库异常记日志后抛给容器,走 500 页
代码 bug(NPE 等)不要 catch,让它 500 并暴露在日志里

Catching an NPE and showing "system busy" hides the bug: the user sees a normal message and the log stays empty, so the defect is never found. Handle only exceptions you know how to handle.

Friends & Partners