详解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 相关文章推荐
SpringBoot实现异步事件驱动的方法
Jun 28 Java/Android
JavaWeb 入门篇:创建Web项目,Idea配置tomcat
Jul 16 Java/Android
浅谈sql_@SelectProvider及使用注意说明
Aug 04 Java/Android
IDEA2021.2配置docker如何将springboot项目打成镜像一键发布部署
Sep 25 Java/Android
MyBatis自定义SQL拦截器示例详解
Oct 24 Java/Android
使用Spring处理x-www-form-urlencoded方式
Nov 02 Java/Android
Java使用JMeter进行高并发测试
Nov 23 Java/Android
Mybatis-Plus进阶分页与乐观锁插件及通用枚举和多数据源详解
Mar 21 Java/Android
利用Java连接Hadoop进行编程
Jun 28 Java/Android
Spring中bean集合注入的方法详解
Jul 07 Java/Android
一文了解Java动态代理的原理及实现
Jul 07 Java/Android
Android实现获取短信验证码并自动填充
May 21 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
php实现curl模拟ftp上传的方法
2015/07/29 PHP
PHP发送短信代码分享
2015/08/11 PHP
简单的php+mysql聊天室实现方法(附源码)
2016/01/05 PHP
php图片合成方法(多张图片合成一张)
2017/11/25 PHP
PHP如何根据文件头检测文件类型实例代码
2018/10/14 PHP
jQuery EasyUI API 中文文档 - Tabs标签页/选项卡
2011/10/01 Javascript
5个最佳的Javascript日期处理类库分享
2012/04/15 Javascript
推荐40款强大的 jQuery 导航插件和教程(上篇)
2012/09/14 Javascript
JS简单实现移动端日历功能示例
2016/12/28 Javascript
AngularJS中的按需加载ocLazyLoad示例
2017/01/11 Javascript
node使用UEditor富文本编辑器的方法实例
2017/07/11 Javascript
react高阶组件经典应用之权限控制详解
2017/09/07 Javascript
Node.js中使用mongoose操作mongodb数据库的方法
2017/09/12 Javascript
jQuery 禁止表单用户名、密码自动填充功能
2017/10/30 jQuery
JS实现的base64加密解密操作示例
2018/04/18 Javascript
在vscode里使用.vue代码模板的方法
2018/04/28 Javascript
Vue-cli3.X使用px2 rem遇到的问题及解决方法
2019/08/08 Javascript
layui将table转化表单显示的方法(即table.render转为表单展示)
2019/09/24 Javascript
vue和iview实现Scroll 数据无限滚动功能
2019/10/31 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
2020/12/09 Javascript
[04:19]完美世界携手游戏风云打造 卡尔工作室模型介绍篇
2013/04/24 DOTA
浅谈python内置变量-reversed(seq)
2017/06/21 Python
Python3爬虫学习之爬虫利器Beautiful Soup用法分析
2018/12/12 Python
Python设计模式之享元模式原理与用法实例分析
2019/01/11 Python
Python Web版语音合成实例详解
2019/07/16 Python
关于python中plt.hist参数的使用详解
2019/11/28 Python
PyTorch和Keras计算模型参数的例子
2020/01/02 Python
Python selenium键盘鼠标事件实现过程详解
2020/07/28 Python
为世界各地的女性设计和生产时尚服装:ROMWE
2016/09/17 全球购物
Wiggle新西兰:自行车、跑步、游泳
2020/05/06 全球购物
音乐教学案例
2014/01/30 职场文书
工作决心书范文
2014/03/11 职场文书
投标保密承诺书
2014/05/19 职场文书
村党的群众路线教育实践活动总结材料
2014/10/31 职场文书
2015年环卫处个人工作总结
2015/07/27 职场文书
Python人工智能之混合高斯模型运动目标检测详解分析
2021/11/07 Python