异常处理流程及原理

异常处理流程

  1. 执行目标方法,目标方法运行期间有任何异常都会被catch捕获,并标志当前请求结束,dispatchException抛出异常
    在这里插入图片描述

  2. 进入视图解析流程,并渲染页面,发生异常时,参数mv为空,传入捕获的异常dispatchException
    在这里插入图片描述

  3. 处理handler发生的异常,处理完成返回ModelAndView
    在这里插入图片描述
    (1)遍历所有的HandlerExceptionResolvers,找到可以处理当前异常的解析器来解析异常
    在这里插入图片描述
    (2)调用resolveException解析异常,传入requestresponse对象,哪个方法,发生的异常,然后自定义异常处理返回ModelAndView
    在这里插入图片描述
    (3)系统默认的异常解析器
    在这里插入图片描述

    DefaultErrorAttributes先来处理异常,把异常信息保存到request域并返回null
    在这里插入图片描述
    ExceptionHandlerExceptionResolver用来处理标注了@ExceptionHandler注解的方法异常

    ResponseStatusExceptionResolver用来处理标注了@ResponseStatus注解的方法异常

    DefaultHandlerExceptionResolver默认的处理器异常解析器,处理一些常见的异常

    (4)如果没有任何解析器能够处理异常,异常就会抛出
    在这里插入图片描述

    (5)如果没有任何解析器能够处理当前异常,最终就会发送/error请求,将保存的异常信息转发到/errorBasicErrorController专门来处理/error请求,BasicErrorController会遍历所有的ErrorViewResolver解析错误视图,如果没有自定义的错误视图解析器,就会使用默认的DefaultErrorViewResolver,会把响应码作为错误页的地址,模板引擎最终响应这个页面。

几种异常处理方式及原理

  1. 自定义错误页,error/404.htmlerror/5xx.html。有精确的错误状态码页面就匹配精确,没有就找 4xx.html,如果都没有就触发白页
  2. 使用@ControllerAdvice@ExceptionHandler处理全局异常,底层是ExceptionHandlerExceptionResolver 支持的
    在这里插入图片描述
  3. 使用@ResponseStatus和自定义异常。底层是 ResponseStatusExceptionResolver ,底层调用 response.sendError(statusCode, resolvedReason),Tomcat会收到一个error。请求最后new一个空的ModelAndView返回,这样任何处理解析器都处理不了当前的异常,最终就会发送/error请求,BasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  4. Spring底层的异常,如参数类型转换异常。底层是DefaultHandlerExceptionResolver 处理框架底层的异常,底层也是response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE),Tomcat会收到一个error。请求最后new一个空的ModelAndView返回,这样任何处理解析器都处理不了当前的异常,最终就会发送/error请求,BasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面
protected ModelAndView doResolveException(
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {

		try {
			if (ex instanceof HttpRequestMethodNotSupportedException) {
				return handleHttpRequestMethodNotSupported(
						(HttpRequestMethodNotSupportedException) ex, request, response, handler);
			}
			else if (ex instanceof HttpMediaTypeNotSupportedException) {
				return handleHttpMediaTypeNotSupported(
						(HttpMediaTypeNotSupportedException) ex, request, response, handler);
			}
			else if (ex instanceof HttpMediaTypeNotAcceptableException) {
				return handleHttpMediaTypeNotAcceptable(
						(HttpMediaTypeNotAcceptableException) ex, request, response, handler);
			}
			else if (ex instanceof MissingPathVariableException) {
				return handleMissingPathVariable(
						(MissingPathVariableException) ex, request, response, handler);
			}
			else if (ex instanceof MissingServletRequestParameterException) {
				return handleMissingServletRequestParameter(
						(MissingServletRequestParameterException) ex, request, response, handler);
			}
			else if (ex instanceof ServletRequestBindingException) {
				return handleServletRequestBindingException(
						(ServletRequestBindingException) ex, request, response, handler);
			}
			else if (ex instanceof ConversionNotSupportedException) {
				return handleConversionNotSupported(
						(ConversionNotSupportedException) ex, request, response, handler);
			}
			else if (ex instanceof TypeMismatchException) {
				return handleTypeMismatch(
						(TypeMismatchException) ex, request, response, handler);
			}
			else if (ex instanceof HttpMessageNotReadableException) {
				return handleHttpMessageNotReadable(
						(HttpMessageNotReadableException) ex, request, response, handler);
			}
			else if (ex instanceof HttpMessageNotWritableException) {
				return handleHttpMessageNotWritable(
						(HttpMessageNotWritableException) ex, request, response, handler);
			}
			else if (ex instanceof MethodArgumentNotValidException) {
				return handleMethodArgumentNotValidException(
						(MethodArgumentNotValidException) ex, request, response, handler);
			}
			else if (ex instanceof MissingServletRequestPartException) {
				return handleMissingServletRequestPartException(
						(MissingServletRequestPartException) ex, request, response, handler);
			}
			else if (ex instanceof BindException) {
				return handleBindException((BindException) ex, request, response, handler);
			}
			else if (ex instanceof NoHandlerFoundException) {
				return handleNoHandlerFoundException(
						(NoHandlerFoundException) ex, request, response, handler);
			}
			else if (ex instanceof AsyncRequestTimeoutException) {
				return handleAsyncRequestTimeoutException(
						(AsyncRequestTimeoutException) ex, request, response, handler);
			}
		}
		catch (Exception handlerEx) {
			if (logger.isWarnEnabled()) {
				logger.warn("Failure while trying to resolve exception [" + ex.getClass().getName() + "]", handlerEx);
			}
		}
		return null;
	}
  1. 自定义实现 HandlerExceptionResolver 处理异常,可以作为默认的全局异常处理规则
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@Component
public class CustomerHandlerExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        try {
            response.sendError(521,"I love you !");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ModelAndView();
    }
}

在这里插入图片描述

  1. ErrorViewResolver 实现自定义处理异常。
    (1)底层调用response.sendError时 ,error请求就会默认转给basicErrorControllerBasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面
    (2)如果异常没有任何解析器能处理,tomcat底层 也会调用response.sendErrorerror请求就会默认转给basicErrorControllerBasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面。
    (3)basicErrorController 要去的页面地址是由 ErrorViewResolver这个错误视图解析器决定的,即适配4xx.html或者5xx.html页面。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java的异常处理机制是一种强大的错误处理工具,它允许程序在遇到运行时错误或意外情况时优雅地继续执行,而不是突然崩溃。这个机制基于三个关键字:`try`、`catch` 和 `finally`。 **工作原理:** 1. **try块**:这部分包含可能会抛出异常的代码。如果这段代码执行过程中发生了异常,控制权就会立即转移到与之匹配的`catch`块。 2. **catch块**:当`try`块中的异常发生时,程序会寻找与该异常类型匹配的`catch`块。如果找到匹配的`catch`,异常将被传递给这个块,这里可以处理异常并提供相应的解决方案。如果没有找到匹配的`catch`,异常将向上层调用栈继续传播,直到找到合适的处理者。 3. **finally块**:无论是否发生异常,`finally`块中的代码总是会被执行。这通常用于资源管理,比如关闭文件流、数据库连接等。`finally`块确保这些清理操作一定会被执行。 4. **throw关键字**:除了由`try`块中的代码自然引发的异常外,还可以使用`throw`手动抛出一个异常,以模拟某种预期之外的情况。 5. **throws关键字**:如果一个方法可能抛出但又没有直接处理异常,那么就需要在方法签名上使用`throws`声明异常,让调用它的代码负责处理。 **相关问题--:** 1. 异常处理流程是如何的? 2. Java中如何定义和使用自定义异常? 3. 什么是`finally`块,何时使用它? 4. 如何通过`try-catch-finally`结构管理资源?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值