HandlerExceptionResolver异常处理
HandlerExceptionResolver是专门进行异常处理的,在render之前进行工作,从异常中解析出ModelAndView
public interface HandlerExceptionResolver {
ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
}
-
DefaultHandlerExceptionResolver 根据不同类型的异常来进行解析,response.sendError设置不同的错误码
response.sendError(HttpServletResponse.SC_NOT_FOUND);
-
ExceptionHandlerExceptionResolver 使用@ExceptionHandler注解的方法来进行异常解析
-
ResponseStatusExceptionResolver 解析有@ResponseStatus注解的异常
-
SimpleMappingExceptionResolver 通过配置的异常类和View的映射关系来解析异常
ExceptionHandlerExceptionResolver
我一般都是使用@ExceptionHandler注解,所以就以ExceptionHandlerExceptionResolver为例
所有的HandlerExceptionResolver实现类都是去重写resolveException方法
// org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver#resolveException
@Override
public ModelAndView resolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 判断当前HandlerExceptionResolver是否可以解析
if (shouldApplyTo(request, handler)) {
// 判断是否禁用缓存,如果禁用缓存的话,设置响应头
prepareResponse(ex, response);
// 具体的处理逻辑
ModelAndView result = doResolveException(request, response, handler, ex);
if (result != null) {
// Explicitly configured warn logger in logException method.
logException(ex, request);
}
return result;
}
else {
return null;
}
}
shouldApplyTo
// org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver#shouldApplyTo
@Override
protected boolean shouldApplyTo(HttpServletRequest request, Object handler) {
if (handler == null) {
return super.shouldApplyTo(request, handler);
}
else if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
handler = handlerMethod.getBean();
return super.shouldApplyTo(request, handler);
}
else {
return false;
}
}
// org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver#shouldApplyTo
protected boolean shouldApplyTo(HttpServletRequest request, Object handler) {
if (handler != null) {
// mappedHandlers是处理器的集合
if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
return true;
}
// mappedHandlerClasses是处理器类型的集合
if (this.mappedHandlerClasses != null) {
for (Class<?> handlerClass : this.mappedHandlerClasses) {
if (handlerClass.isInstance(handler)) {
return true;
}
}
}
}
// Else only apply if there are no explicit handler mappings.
return (this.mappedHandlers == null && this.mappedHandlerClasses == null);
}
doResolveException
该方法是处理异常的实际方法
protected final ModelAndView doResolveException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
}
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
// 找到处理异常的方法
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
}
// 设置argumentResolvers和returnValueHandlers
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
try {
Throwable cause = exception.getCause();
if (cause != null) {
// Expose cause as provided argument as well
// 执行exceptionHandler方法解析异常
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);
}
else {
// Otherwise, just the given exception as-is
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);
}
}
catch (Throwable invocationEx) {
// Continue with default processing of the original exception...
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());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}
}
https://zhhll.icu/2021/框架/springmvc/底层剖析/5.HandlerExceptionResolver/
本文由mdnice多平台发布
网友评论