异常处理流程

执行目标方法,目标方法运行期间有任何异常都会被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)
@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();
    }
}

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异常处理流程及原理内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!