Servlet 异常错误处理
当一个 Servlet 抛出异常时,Servlet 容器会去 web.xml 中检查是否配置了对应的 <error-page> 来显示异常信息。可以为不同的异常类型或 HTTP 错误码配置不同的错误页面。
通过错误响应码设置错误页面
首先配置一个用于显示异常信息的 Servlet 及其映射:
<!-- 显示异常信息的Servlet -->
<servlet>
<servlet-name>errorservlet</servlet-name>
<servlet-class>MyErrorServlet</servlet-class>
</servlet>
<!-- servlet 映射 -->
<servlet-mapping>
<servlet-name>errorservlet</servlet-name>
<url-pattern>/error</url-pattern>
</servlet-mapping>Code language: HTML, XML (xml)
通过错误码配置错误页面,当发生 404 错误时跳转到 /error:
<error-page>
<error-code>404</error-code>
<location>/error</location>
</error-page>Code language: HTML, XML (xml)
对应的 MyErrorServlet 类:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/MyErrorServlet")
public class MyErrorServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().append("出错了");
}
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
super.service(arg0, arg1);
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
super.service(arg0, arg1);
}
}Code language: JavaScript (javascript)
注意:如果运行时出现以下错误:
java.lang.ClassCastException: org.eclipse.wst.server.preview.internal.WTPErrorHandler cannot be cast to org.eclipse.jetty.servlet.ErrorPageErrorHandlerCode language: CSS (css)说明你配置的服务器不是 Tomcat,建议将 Eclipse 的服务器运行时环境配置为 Tomcat 服务器。
访问一个不存在的 URL 地址时,将触发 404 错误并跳转到 /error 对应的 Servlet。
通过异常类型设置错误页面
除了按错误码配置,还可以为特定的异常类型指定处理 Servlet:
<error-page>
<exception-type>java.io.IOException</exception-type>
<location>/error2</location>
</error-page>Code language: HTML, XML (xml)
当出现 IOException 时,交由 /error2 地址对应的 Servlet 处理。
异常信息展示 Servlet 示例
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/MyErrorServlet")
public class MyErrorServlet2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception"); // 获取异常对象
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); // 获取错误状态码
String servletName = (String) request.getAttribute("javax.servlet.error.servlet_name"); // Servlet 的名称
if (servletName == null) {
servletName = "Unknown";
}
String requestUri = (String) request.getAttribute("javax.servlet.error.request_uri");
if (requestUri == null) {
requestUri = "Unknown";
}
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "foxdevelop.com Error/Exception 信息";
String docType = "<!DOCTYPE html>\n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body>\n");
out.println("<h1>显示错误信息</h1>");
if (throwable == null && statusCode == null) {
out.println("<h2>错误信息丢失</h2>");
out.println("请返回 <a href=\"" +
response.encodeURL("http://localhost:8080/") +
"\">主页</a>。");
} else if (statusCode != null) {
out.println("错误代码 : " + statusCode);
} else {
out.println("<h2>错误信息</h2>");
out.println("Servlet Name : " + servletName +
"</br></br>");
out.println("异常类型 : " +
throwable.getClass().getName() +
"</br></br>");
out.println("请求 URI: " + requestUri +
"<br><br>");
out.println("异常信息: " +
throwable.getMessage());
}
out.println("</body>");
out.println("</html>");
}
@Override
protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
throws ServletException, IOException {
super.service(arg0, arg1);
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
super.service(arg0, arg1);
}
}Code language: JavaScript (javascript)
配置该 Servlet
<servlet>
<servlet-name>MyErrorServlet2</servlet-name>
<servlet-class>MyErrorServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyErrorServlet2</servlet-name>
<url-pattern>/err2</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>java.io.IOException</exception-type>
<location>/err2</location>
</error-page>Code language: HTML, XML (xml)
在另一个 Servlet 的 doGet 中抛出异常:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
throw new IOException("");
}Code language: JavaScript (javascript)
访问该 Servlet 时,会触发 IOException,容器将跳转到 /err2 对应的 Servlet 显示异常详情。
全局异常捕获
如果希望所有未捕获的异常都通过同一个 Servlet 处理,可以配置 java.lang.Throwable 类型:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/err3</location>
</error-page>Code language: HTML, XML (xml)
这样无论抛出何种异常,都会交由 /err3 对应的 Servlet 统一处理。
错误页面中可用的请求属性
| 属性名 | 类型 | 说明 |
|---|---|---|
javax.servlet.error.exception | Throwable | 异常对象 |
javax.servlet.error.status_code | Integer | HTTP 状态码 |
javax.servlet.error.servlet_name | String | 发生异常的 Servlet 名称 |
javax.servlet.error.request_uri | String | 引发异常的请求 URI |
Previous: Servlet 过滤器Filter
Next: Servlet Cookie 处理