根据Servlet Specification:
servlet或过滤器可能会在以下过程中引发以下异常
处理请求:
运行时异常或错误
ServletExceptions或其子类
IOExceptions或其子类
如果我们查看org.springframework.web.servlet.FrameworkServlet#processRequest
,我们会看到Spring抛出ServletException
和IOException
,但是包装了其他内容,包括RuntimeExceptions
:
try {
doService(request, response);
} catch (ServletException | IOException ex) {
failureCause = ex;
throw ex;
} catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
Spring为什么不像
RuntimeException
那样处理IOException
?UPD:换句话说,如果他们以这种方式处理异常,将会发生什么错误:
try {
doService(request, response);
} catch (ServletException | IOException | RuntimeException ex) {
failureCause = ex;
throw ex;
} catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
最佳答案
这是必需的,因为在doService
中调用的受保护抽象processRequest
方法会抛出任何选中或未选中的Exception
。
protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception;
现在,假设您像这样覆盖
doService
:@Override
protected void doService(Long request, Long response) throws ClassNotFoundException {
// whatever ...
}
这是完全合法的,但是
processRequest
可能会抛出ClassNotFoundException
,您必须将其声明为已检查的异常。而且,由于processRequest
,doGet
和其他API方法使用了doPost
,因此这些方法也必须声明ClassNotFoundException
,这违反了规范。请注意,这主要适用于
doService
不是org.springframework.web.servlet.DispatcherServlet
提供的实现的情况。 doService
中的DispatcherServlet
调用doDispatch
,并且doDispatch
已经捕获了除ServletException
或IOException
以外的所有内容。但是,仍然需要再次捕获异常,因为doService
和doDispatch
的声明并不将其检查的异常列表限制为ServletException
和IOException
。编辑21/11/2019:
在您的替代异常处理约定中,我看不到任何麻烦。确实更接近按字面解释的规范。
该实现只是包装了不是ServletException或IOException的所有内容。
可能是因为以后处理程序对异常类型敏感。但这至少不是DefaultHandlerExceptionResolver使用的DispatcherServlet的情况。
我看不到任何可能影响使用
<error-page><exception-type>...</exception-type></error-page>
或使用@Component
实现ErrorPageRegistrar
的web.xml中的错误处理的明显问题。