根据Servlet Specification


  servlet或过滤器可能会在以下过程中引发以下异常
  处理请求:
  
  
  运行时异常或错误
  ServletExceptions或其子类
  IOExceptions或其子类
  


如果我们查看org.springframework.web.servlet.FrameworkServlet#processRequest,我们会看到Spring抛出ServletExceptionIOException,但是包装了其他内容,包括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,您必须将其声明为已检查的异常。而且,由于processRequestdoGet和其他API方法使用了doPost,因此这些方法也必须声明ClassNotFoundException,这违反了规范。

请注意,这主要适用于doService不是org.springframework.web.servlet.DispatcherServlet提供的实现的情况。 doService中的DispatcherServlet调用doDispatch,并且doDispatch已经捕获了除ServletExceptionIOException以外的所有内容。但是,仍然需要再次捕获异常,因为doServicedoDispatch的声明并不将其检查的异常列表限制为ServletExceptionIOException

编辑21/11/2019:

在您的替代异常处理约定中,我看不到任何麻烦。确实更接近按字面解释的规范。
该实现只是包装了不是ServletException或IOException的所有内容。
可能是因为以后处理程序对异常类型敏感。但这至少不是DefaultHandlerExceptionResolver使用的DispatcherServlet的情况。

我看不到任何可能影响使用<error-page><exception-type>...</exception-type></error-page>或使用@Component实现ErrorPageRegistrar的web.xml中的错误处理的明显问题。

09-30 15:38
查看更多