Spring MVC : 异常处理场景总结

本文详细解析了SpringMVC框架中的异常处理机制,包括@ExceptionHandler、SimpleMappingExceptionResolver及@ResponseStatus注解的使用,阐述了全处理、半处理与未处理三种异常处理情况,并分析了Tomcat中异常处理的具体流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过Spring MVC 可以通过如下方式对异常进行处理 :

  1. 通过@ExceptionHandler指定某类异常被特定的控制器处理方法处理;
    该异常处理控制其处理方法又可以分几种情况 :
    • 不再抛出该异常,自身逻辑处理异常,直接写response对象输出异常信息;

      全处理

    • 不再抛出该异常,自身根据异常相应返回一个View/ModelAndView交由框架渲染异常信息到response

      全处理

    • 不再抛出该异常,自身逻辑根据异常信息执行了一些逻辑,并相应地调用response.sendError ;

      半处理

    • 继续抛出异常,自身可能对异常信息做了某些记录,不过仍然继续抛出该异常;

      未处理

  2. 通过SimpleMappingExceptionResolver指定处理异常的视图;

    全处理

  3. 使用注解@ResponseStatus注解异常;

    半处理

    • 不再继续抛出该异常,而是相应地调用response.sendError

上面Spring MVC 的异常处理机制,总结来看,有三种处理情况 :

  1. 全处理
  2. 半处理
  3. 未处理

业务请求过程中出现异常的话,Spring MVC 会首先尝试使用上面所提到的机制处理该异常。然后 :

  1. 如果该异常能被以上机制全处理,相应的响应结果会直接返回给请求者,请求处理结束;
  2. 如果该异常被以上机制半处理,也就是说,逻辑遇到异常时捕获了异常,相应地调用了response.sendError,然后控制权返回Servlet容器,此时Servlet容器会尝试根据response.sendError设置的status/reason寻找相应的错误处理页面,重新发起(forward)一个错误页面请求;
  3. 如果该异常未被以上机制处理,也就是说被继续抛出直到Servlet容器,Servlet容器会捕获该异常找到对应的错误处理页面,否则同样调用跟response.sendError类似的逻辑设置状态字为500,然后接下来,根据所设置的status/eason寻找相应的错误处理页面,重新发起(forward)一个错误页面请求;

代码附件

  1. 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();
    }
  1. 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方法。

相关文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值