千家信息网

SpringBoot异常处理的原理分析

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,这篇文章主要介绍"SpringBoot异常处理的原理分析"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"SpringBoot异常处理的原理分析"文章能帮助大家解
千家信息网最后更新 2025年01月20日SpringBoot异常处理的原理分析

这篇文章主要介绍"SpringBoot异常处理的原理分析"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"SpringBoot异常处理的原理分析"文章能帮助大家解决问题。

异常处理流程

执行目标方法,目标方法运行期间有任何异常都会被catch捕获,并标志当前请求结束,dispatchException抛出异常

进入视图解析流程,并渲染页面,发生异常时,参数mv为空,传入捕获的异常dispatchException

处理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;        }

5.自定义实现 HandlerExceptionResolver 处理异常,可以作为默认的全局异常处理规则

@Order(value = Ordered.HIGHEST_PRECEDENCE)@Componentpublic 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();    }}

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页面。

关于"SpringBoot异常处理的原理分析"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

0