探索app小游戏的多样化发展与未来趋势
1303
2023-01-07
详解SpringBoot异常处理流程及原理
异常处理流程
执行目标方法,目标方法运行期间有任何异常都会被catch捕获,并标志当前请求结束,dispatchException抛出异常
进入视图解析流程,并渲染页面,发生异常时,参数mv为空,传入捕获的异常dispatchException
处理handler发生的异常,处理完成返回ModelAndView
(1)遍历所有的HandlerExceptionResolvers,找到可以处理当前异常的解析器来解析异常
(2)调用resolveException解析异常,传入request和response对象,哪个方法,发生的异常,然后自定义异常处理返回ModelAndView
(3)系统默认的异常解析器
① DefaultErrorAttributes先来处理异常,把异常信息保存到request域并返回null
② ExceptionHandlerExceptionResolver用来处理标注了@ExceptionHandler注解的方法异常
③ ResponseStatusExceptionResolver用来处理标注了@ResponseStatus注解的方法异常
④ DefaultHandlerExceptionResolver默认的处理器异常解析器,处理一些常见的异常
(4)如果没有任何解析器能够处理异常,异常就会抛出
(5)如果没有任何解析器能够处理当前异常,最终就会发送/error请求,将保存的异常信息转发到/error。BasicErrorController专门来处理/error请求,BasicErrorController会遍历所有的ErrorViewResolver解析错误视图,如果没有自定义的错误视图解析器,就会使用默认的DefaultErrorViewResolver,会把响应码作为错误页的地址,模板引擎最终响应这个页面。
几种异常处理方式及原理
1.自定义错误页,error/404.html、error/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请求就会默认转给basicErrorController,BasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面
(2)如果异常没有任何解析器能处理,tomcat底层 也会调用response.sendError。error请求就会默认转给basicErrorController,BasicErrorController专门来处理/error请求,适配4xx.html或者5xx.html页面。
(3)basicErrorController 要去的页面地址是由 ErrorViewResolver这个错误视图解析器决定的,即适配4xx.html或者5xx.html页面。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~