通过Spring MVC
可以通过如下方式对异常进行处理 :
- 通过
@ExceptionHandler
指定某类异常被特定的控制器处理方法处理;
该异常处理控制其处理方法又可以分几种情况 :- 不再抛出该异常,自身逻辑处理异常,直接写
response
对象输出异常信息;全处理
- 不再抛出该异常,自身根据异常相应返回一个
View
/ModelAndView
交由框架渲染异常信息到response
;全处理
- 不再抛出该异常,自身逻辑根据异常信息执行了一些逻辑,并相应地调用
response.sendError
;半处理
- 继续抛出异常,自身可能对异常信息做了某些记录,不过仍然继续抛出该异常;
未处理
- 不再抛出该异常,自身逻辑处理异常,直接写
- 通过
SimpleMappingExceptionResolver
指定处理异常的视图;全处理
- 使用注解
@ResponseStatus
注解异常;半处理
- 不再继续抛出该异常,而是相应地调用
response.sendError
- 不再继续抛出该异常,而是相应地调用
上面Spring MVC
的异常处理机制,总结来看,有三种处理情况 :
- 全处理
- 半处理
- 未处理
业务请求过程中出现异常的话,Spring MVC
会首先尝试使用上面所提到的机制处理该异常。然后 :
- 如果该异常能被以上机制全处理,相应的响应结果会直接返回给请求者,请求处理结束;
- 如果该异常被以上机制半处理,也就是说,逻辑遇到异常时捕获了异常,相应地调用了
response.sendError
,然后控制权返回Servlet
容器,此时Servlet
容器会尝试根据response.sendError
设置的status/reason
寻找相应的错误处理页面,重新发起(forward
)一个错误页面请求; - 如果该异常未被以上机制处理,也就是说被继续抛出直到
Servlet
容器,Servlet
容器会捕获该异常找到对应的错误处理页面,否则同样调用跟response.sendError
类似的逻辑设置状态字为500
,然后接下来,根据所设置的status/eason
寻找相应的错误处理页面,重新发起(forward
)一个错误页面请求;
代码附件
Tomcat
中遇到请求处理异常时调用response.setError
的有关逻辑
// 这是 Servlet 容器 Tomcat 遇到请求处理过程中的异常时,所做的反应,
// 这是类 StandardWrapperValve 的代码片段
private void exception(Request request, Response response,
Throwable exception) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, exception);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setError();
}
Tomcat Response
提供给调用者使用的response.sendError
的逻辑实现
// 这是 Tomcat 中 Response类 的代码实现片段
@Override
public void sendError(int status, String message) throws IOException {
if (isCommitted()) {
throw new IllegalStateException
(sm.getString("coyoteResponse.sendError.ise"));
}
// Ignore any call from an included servlet
if (included) {
return;
}
setError();
getCoyoteResponse().setStatus(status);
getCoyoteResponse().setMessage(message);
// Clear any data content that has been buffered
resetBuffer();
// Cause the response to be finished (from the application perspective)
setSuspended(true);
}
注意以上两端代码的相同之处:都会对响应对象调用#setError
,#setStatus
方法。