Java Web 异常处理:Servlet 错误页面与异常拦截机制
在 Java Web 应用中,异常处理是保障应用稳定性和用户体验的关键环节。Servlet 容器提供了灵活的异常处理机制,允许开发者通过配置错误页面或自定义异常处理器,统一捕获和处理请求过程中出现的异常(如 404 资源不存在、500 服务器错误、自定义业务异常等)。本文将详细解析 Servlet 异常处理的配置方式、核心对象及实践技巧。
Servlet 异常处理的核心机制
Servlet 容器通过错误页面配置和异常属性传递实现异常处理:
- 当应用抛出未捕获的异常或返回特定错误码(如 404、500)时,容器会拦截请求;
- 根据预配置的规则(错误码或异常类型),将请求转发到指定的错误处理器(如 Servlet、JSP);
- 容器在请求域中设置异常相关属性,供错误处理器获取详细信息(如错误码、异常堆栈)。
异常处理的配置方式
XML 配置(web.xml)
通过 web.xml 的 <error-page> 标签配置错误页面,支持按错误码或异常类型匹配:
(1)按错误码配置
针对 HTTP 状态码(如 404、500)指定处理页面:
1 | <!-- 处理 404 资源不存在错误 --> |
(2)按异常类型配置
针对特定异常类型(如 ArithmeticException、自定义 BusinessException)指定处理页面:
1 | <!-- 处理算术异常(如除以零) --> |
注解配置(Servlet 3.0+)
Servlet 3.0 及以上支持通过注解 @WebServlet 的 errorPage 属性配置错误页面,或直接在异常处理器上使用 @WebServlet 并结合 web.xml 的 <error-page>。
示例:自定义异常处理 Servlet
1 |
|
获取异常信息:请求域中的异常属性
当容器将请求转发到错误处理器时,会在 HttpServletRequest 的请求域中设置以下属性,用于获取异常详情:
| 属性键 | 类型 | 描述 |
|---|---|---|
javax.servlet.error.status_code |
Integer |
HTTP 状态码(如 404、500) |
javax.servlet.error.exception_type |
Class<?> |
异常类型的 Class 对象(如 ArithmeticException.class) |
javax.servlet.error.message |
String |
错误消息(如异常的 getMessage() 内容) |
javax.servlet.error.request_uri |
String |
触发异常的请求 URI(如 /user/123) |
javax.servlet.error.exception |
Throwable |
异常对象(可调用 printStackTrace() 打印堆栈) |
javax.servlet.error.servlet_name |
String |
触发异常的 Servlet 名称(如 UserServlet) |
示例:在异常处理器中获取信息
1 |
|
异常处理的执行流程
- 异常触发:
- 应用抛出未捕获的异常(如
throw new ArithmeticException()); - 容器返回特定 HTTP 状态码(如请求不存在资源时返回 404)。
- 应用抛出未捕获的异常(如
- 容器拦截:
容器根据web.xml的<error-page>配置,匹配错误码或异常类型。 - 转发请求:
容器将请求转发到<location>指定的错误处理器(Servlet 或 JSP),并在请求域中设置异常属性。 - 处理响应:
错误处理器读取请求域中的异常信息,生成友好的错误页面返回给客户端。
最佳实践
统一错误页面:
为常见错误码(404、500)和通用异常(Exception)配置统一处理页面,避免用户看到原始异常堆栈。区分环境:
- 开发环境:显示详细异常信息(便于调试);
- 生产环境:显示友好提示(如 “系统繁忙,请稍后再试”),同时记录详细日志。
日志记录:
在异常处理器中通过日志框架(如 Logback、Log4j)记录异常堆栈,便于问题排查:1
2
3// 记录异常日志
Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);
logger.error("请求 {} 发生错误", requestUri, exception);
自定义异常类型:
定义业务异常(如BusinessException),并为其配置专属处理器,实现业务与系统异常的分离处理。避免循环错误:
确保错误处理器本身不会抛出异常,否则容器可能返回默认错误页面(如 Tomcat 的 404 页面)