您好,登录后才能下订单哦!
在Web应用开发中,异常处理是一个非常重要的环节。SpringMVC作为Java Web开发的主流框架之一,提供了强大的异常处理机制。本文将深入分析SpringMVC异常处理的源码,帮助读者理解其工作原理和实现细节。
SpringMVC的异常处理机制主要通过HandlerExceptionResolver
接口来实现。该接口定义了处理控制器方法执行过程中抛出的异常的方法。SpringMVC提供了多种实现类,如DefaultHandlerExceptionResolver
、ExceptionHandlerExceptionResolver
等,用于处理不同类型的异常。
HandlerExceptionResolver
接口是SpringMVC异常处理的核心接口,定义如下:
public interface HandlerExceptionResolver {
ModelAndView resolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex);
}
该接口只有一个方法resolveException
,用于解析并处理异常。参数handler
是抛出异常的处理器(通常是Controller方法),ex
是抛出的异常。
SpringMVC默认提供了多个HandlerExceptionResolver
的实现类,其中最常用的是DefaultHandlerExceptionResolver
和ExceptionHandlerExceptionResolver
。
DefaultHandlerExceptionResolver
是SpringMVC默认的异常处理器,用于处理常见的HTTP错误,如404、500等。其源码如下:
public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
@Override
protected ModelAndView doResolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
try {
if (ex instanceof NoSuchRequestHandlingMethodException) {
return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) ex, request, response, handler);
} else 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 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 handleMethodArgumentNotValid((MethodArgumentNotValidException) ex, request, response, handler);
} else if (ex instanceof MissingServletRequestPartException) {
return handleMissingServletRequestPart((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);
}
} catch (Exception handlerException) {
logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
}
return null;
}
}
DefaultHandlerExceptionResolver
通过判断异常类型,调用相应的处理方法。例如,如果抛出的是NoSuchRequestHandlingMethodException
异常,则调用handleNoSuchRequestHandlingMethod
方法进行处理。
ExceptionHandlerExceptionResolver
是另一个重要的异常处理器,用于处理通过@ExceptionHandler
注解定义的异常处理方法。其源码如下:
public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver {
@Override
protected ModelAndView doResolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handler, ex);
if (exceptionHandlerMethod == null) {
return null;
}
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
try {
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, ex);
} catch (Exception invocationEx) {
logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
return null;
}
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
} else {
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
return mav;
}
}
}
ExceptionHandlerExceptionResolver
通过getExceptionHandlerMethod
方法获取处理当前异常的@ExceptionHandler
方法,然后调用invokeAndHandle
方法执行该方法,并返回相应的ModelAndView
。
除了使用SpringMVC提供的默认异常处理器外,开发者还可以通过实现HandlerExceptionResolver
接口或使用@ControllerAdvice
注解来自定义异常处理。
开发者可以通过实现HandlerExceptionResolver
接口来自定义异常处理器。例如:
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("exception", ex);
modelAndView.setViewName("error");
return modelAndView;
}
}
然后,在Spring配置文件中注册该异常处理器:
<bean class="com.example.CustomHandlerExceptionResolver"/>
@ControllerAdvice
注解是SpringMVC提供的一种全局异常处理机制。通过该注解,开发者可以定义一个全局的异常处理类,处理所有控制器抛出的异常。例如:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("exception", ex);
modelAndView.setViewName("error");
return modelAndView;
}
}
@ControllerAdvice
注解的类会自动被SpringMVC扫描并注册为全局异常处理器。
SpringMVC的异常处理流程如下:
HandlerExceptionResolver
的resolveException
方法。HandlerExceptionResolver
成功处理了异常,则返回相应的ModelAndView
。HandlerExceptionResolver
能够处理异常,则继续抛出异常,最终由Servlet容器处理。DispatcherServlet
是SpringMVC的核心控制器,负责处理所有的HTTP请求。在DispatcherServlet
的processHandlerException
方法中,会调用所有注册的HandlerExceptionResolver
来处理异常:
protected ModelAndView processHandlerException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) throws Exception {
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
if (exMv != null) {
if (exMv.isEmpty()) {
return null;
}
return exMv;
}
throw ex;
}
processHandlerException
方法会遍历所有注册的HandlerExceptionResolver
,直到某个HandlerExceptionResolver
成功处理异常并返回ModelAndView
。
ExceptionHandlerExceptionResolver
是SpringMVC中用于处理@ExceptionHandler
注解的异常处理器。其核心方法是doResolveException
,源码如下:
@Override
protected ModelAndView doResolveException(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handler, ex);
if (exceptionHandlerMethod == null) {
return null;
}
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
try {
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, ex);
} catch (Exception invocationEx) {
logger.error("Failed to invoke @ExceptionHandler method: " + exceptionHandlerMethod, invocationEx);
return null;
}
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
} else {
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
return mav;
}
}
doResolveException
方法首先通过getExceptionHandlerMethod
方法获取处理当前异常的@ExceptionHandler
方法,然后调用invokeAndHandle
方法执行该方法,并返回相应的ModelAndView
。
SpringMVC提供了强大的异常处理机制,通过HandlerExceptionResolver
接口和@ExceptionHandler
注解,开发者可以灵活地处理控制器方法执行过程中抛出的异常。本文通过分析SpringMVC异常处理的源码,详细介绍了其工作原理和实现细节,希望能帮助读者更好地理解和使用SpringMVC的异常处理机制。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。