一、异常处理分析
1、Controller调用过程中的异常解析使用
示例代码如下:package com.chj.controllerAdvice;
@ControllerAdvice("com.chj")
public class ExceptionHandlerControllerAdvice {
@ExceptionHandler({ArrayIndexOutOfBoundsException.class})
public @ResponseBody String handlerArrayIndexOutOfBoundsException(Exception e) {
System.out.println("====ExceptionHandlerControllerAdvice-->" + e.getMessage());
return "ArrayIndexOutOfBoundsException";
}
@ExceptionHandler({NullPointerException.class})
public @ResponseBody String handlerNullPointerException(Exception e) {
System.out.println("====ExceptionHandlerControllerAdvice-->" + e.getMessage());
return "NullPointerException";
}
}
类上面加上@ControllerAdvice("com.chj")注解,这个包定义就是只对这个包里面的Controller生效。然后类里面的方法加上@ExceptionHandler({ArrayIndexOutOfBoundsException.class})与@ExceptionHandler
({NullPointerException.class})。
表示这个方法当调用过程中出现注解里面定义的异常时会被调用到,这些方法就是对异常处理的方法。
源码的核心思想差不多
1)收集注解包装成类;
2)建立@ExceptionHandler中异常和Method的映射关系;
3)根据出现的异常从映射关系中找到对应的Method对象;
4)反射调用,这个调用逻辑跟Controller里面具体方法调用逻辑一模一样。
2、异常源码分析
2.1、异常处理源码入口
org.springframework.web.servlet.DispatcherServlet#doDispatch
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
// As of 4.3, we're processing Errors thrown from handler methods as well,
// making them available for @ExceptionHandler methods and other scenarios.
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
如果exception不为空,进行异常处理
org.springframework.web.servlet.DispatcherServlet#processDispatchResult
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
boolean errorView = false;
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException) exception).getModelAndView();
} else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
org.springframework.web.servlet.DispatcherServlet#processHandlerException
@Nullable
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) throws Exception {
// Success and error responses may use different content types
request.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
if (this.handlerExceptionResolvers != null) {
for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
2.2、异常处理抽象方法逻辑处理
该方法最终还是会调用到抽象类里面的resolveException方法:
org.springframework.web.servlet.handler.HandlerExceptionResolverComposite#resolveException
@Override
@Nullable
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler,Exception ex) {
if (this.resolvers != null) {
for (HandlerExceptionResolver handlerExceptionResolver : this.resolvers) {
ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (mav != null) {
return mav;
}
}
}
return null;
}
异常处理抽象方法代码如下:
org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver#resolveException
org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver#doResolveException
@Override
@Nullable
protected final ModelAndView doResolveException(
HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
}
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#doResolveHandlerMethodException
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) {
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
}
if (this.argumentResolvers