详解SpringBoot异常处理流程及原理


Posted in Java/Android onJune 21, 2021

异常处理流程

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

详解SpringBoot异常处理流程及原理

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

详解SpringBoot异常处理流程及原理

处理handler发生的异常,处理完成返回ModelAndView

详解SpringBoot异常处理流程及原理

(1)遍历所有的HandlerExceptionResolvers,找到可以处理当前异常的解析器来解析异常

详解SpringBoot异常处理流程及原理

(2)调用resolveException解析异常,传入requestresponse对象,哪个方法,发生的异常,然后自定义异常处理返回ModelAndView

详解SpringBoot异常处理流程及原理

(3)系统默认的异常解析器

详解SpringBoot异常处理流程及原理

DefaultErrorAttributes先来处理异常,把异常信息保存到request域并返回null

详解SpringBoot异常处理流程及原理

ExceptionHandlerExceptionResolver用来处理标注了@ExceptionHandler注解的方法异常

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

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

(4)如果没有任何解析器能够处理异常,异常就会抛出

详解SpringBoot异常处理流程及原理

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

几种异常处理方式及原理

1.自定义错误页,error/404.htmlerror/5xx.html。有精确的错误状态码页面就匹配精确,没有就找 4xx.html,如果都没有就触发白页

2.使用@ControllerAdvice@ExceptionHandler处理全局异常,底层是ExceptionHandlerExceptionResolver 支持的

详解SpringBoot异常处理流程及原理

3.使用@ResponseStatus和自定义异常。底层是 ResponseStatusExceptionResolver ,底层调用 response.sendError(statusCode, resolvedReason),Tomcat会收到一个error。请求最后new一个空的ModelAndView返回,这样任何处理解析器都处理不了当前的异常,最终就会发送/error请求,BasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面

详解SpringBoot异常处理流程及原理
详解SpringBoot异常处理流程及原理
详解SpringBoot异常处理流程及原理

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)
@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();
    }
}

详解SpringBoot异常处理流程及原理

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异常处理流程及原理的文章就介绍到这了,更多相关SpringBoot异常处理流程及原理内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Java/Android 相关文章推荐
为什么在foreach循环中JAVA集合不能添加或删除元素
Jun 11 Java/Android
SpringAop日志找不到方法的处理
Jun 21 Java/Android
分析Java中Map的遍历性能问题
Jun 26 Java/Android
Spring Boot 实现敏感词及特殊字符过滤处理
Jun 29 Java/Android
解决Jenkins集成SonarQube遇到的报错问题
Jul 15 Java/Android
JVM钩子函数的使用场景详解
Aug 23 Java/Android
Java spring单点登录系统
Sep 04 Java/Android
详解JAVA的控制语句
Nov 11 Java/Android
Java Spring Boot 正确读取配置文件中的属性的值
Apr 20 Java/Android
Flutter Navigator 实现路由传递参数
Apr 22 Java/Android
Java实现带图形界面的聊天程序
Jun 10 Java/Android
Java获取字符串编码格式实现思路
Sep 23 Java/Android
Java新手教程之ArrayList的基本使用
Java各种比较对象的方式的对比总结
Jun 20 #Java/Android
Java Optional<Foo>转换成List<Bar>的实例方法
Jun 20 #Java/Android
详解Java实践之适配器模式
Java数据结构之链表相关知识总结
详解Java实践之抽象工厂模式
Java框架入门之简单介绍SpringBoot框架
You might like
珊瑚虫IP库浅析
2007/02/15 PHP
PHP中读写文件实现代码
2011/10/20 PHP
下拉列表多级联动dropDownList示例代码
2013/06/27 PHP
PHP遍历XML文档所有节点的方法
2015/03/12 PHP
php写入数据到CSV文件的方法
2015/03/14 PHP
php面向对象值单例模式
2016/05/03 PHP
php基于闭包实现函数的自调用(递归)实例分析
2016/11/11 PHP
Jquery选择器 $实现原理
2009/12/02 Javascript
javascript中删除指定数组中指定的元素的代码
2011/02/12 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
js跑马灯代码(自写)
2013/04/17 Javascript
使用js实现按钮控制文本框加1减1应用于小时+分钟
2013/12/09 Javascript
JS操作CSS随机改变网页背景实现思路
2014/03/10 Javascript
Node.js实现的简易网页抓取功能示例
2014/12/05 Javascript
JS原型链怎么理解
2016/06/27 Javascript
微信小程序 支付简单实例及注意事项
2017/01/06 Javascript
微信小程序 扎金花简单实例
2017/02/21 Javascript
Bootstrap 过渡效果Transition 模态框(Modal)
2017/03/17 Javascript
基于Vue、Vuex、Vue-router实现的购物商城(原生切换动画)效果
2018/01/09 Javascript
vue对storejs获取的数据进行处理时遇到的几种问题小结
2018/03/20 Javascript
three.js欧拉角和四元数的使用方法
2020/07/26 Javascript
[10:04]国际邀请赛采访专栏:DK.Farseer,mouz.Black^,采访员Josh专访
2013/08/05 DOTA
跟老齐学Python之有点简约的元组
2014/09/24 Python
Python实现windows下模拟按键和鼠标点击的方法
2015/03/13 Python
K-近邻算法的python实现代码分享
2017/12/09 Python
python如何查看微信消息撤回
2018/11/27 Python
Python实现求两个数组交集的方法示例
2019/02/23 Python
pytorch获取模型某一层参数名及参数值方式
2019/12/30 Python
python获取依赖包和安装依赖包教程
2020/02/13 Python
浅谈django channels 路由误导
2020/05/28 Python
python 高阶函数简单介绍
2021/02/19 Python
从零实现一个自定义html5播放器的示例代码
2017/08/01 HTML / CSS
《母亲的恩情》教学反思
2014/02/13 职场文书
2015年车间管理工作总结
2015/07/23 职场文书
会计岗位工作总结
2015/08/12 职场文书
幼儿园中班教学反思
2016/03/03 职场文书