【springmvc】九大组件之HandlerExceptionResolver
在Spring MVC中,如果对异常不做任何处理,Spring MVC会将异常直接抛给容器。
例如下面的代码抛出了异常:
@GetMapping("e1")
public String exception() {int i = 1 / 0;return "exception";
}
浏览器页面上会显示500错误。
对异常的处理
@ExceptionHandler处理当前Controller的异常
@ExceptionHandler能对当前Controller中指定的异常进行处理,可以通过ModelAndView将异常信息传递给页面。
使用如下:
@GetMapping("e1")
public String exception() {int i = 1 / 0;return "exception";
}@ExceptionHandler(value = RuntimeException.class)
public ModelAndView handlerRuntimeException(Exception exception) {ModelAndView mv = new ModelAndView("error");mv.addObject("exception", exception);return mv;
}
@ExceptionHandler要注意异常的优先级,如果Controller中有如下的异常处理方法,那么还是会执行handlerArithmeticException()方法,因为ArithmeticException异常更加具体:
@ExceptionHandler(value = RuntimeException.class)
public ModelAndView handlerRuntimeException(Exception exception) {ModelAndView mv = new ModelAndView("error");mv.addObject("exception", exception);return mv;
}
@ControllerAdvice处理全局异常
@ExceptionHandler的作用域是当前Controller,如果想对全局的异常进行处理需要使用@ControllerAdvice。
使用如下:
@ControllerAdvice
public class ExceptionHandlerControllerAdvice {@ExceptionHandler(value = ArithmeticException.class)public ModelAndView handlerArithmeticException(Exception exception) {ModelAndView mv = new ModelAndView("error");mv.addObject("exception", exception);return mv;}}
如果Controller中使用了@ExceptionHandler处理异常,那么他的优先级比全局的异常处理高。
@ResponseStatus定制错误码和错误内容
可以使用@ResponseStatus加到异常类上,这样当这个异常抛出时,页面显示的是定制的错误消息。
异常类定义如下:
@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "用户名和密码不匹配")
public class UsernameNotMatchPasswordException extends RuntimeException {}
在方法中抛出这个异常:
/*** 使用@ResponseStatus定义错误码和错误内容* @param i* @return*/
@GetMapping("e3")
public String exception3(int i) {if (13 == i) {throw new UsernameNotMatchPasswordException();}return "success";
}
页面显示的错误消息如下:
使用SimpleMappingExceptionResolver处理指定异常
注入SimpleMappingExceptionResolver,并指定要处理的异常与视图。
com.morris.spring.mvc.config.MVCConfig#extendHandlerExceptionResolvers
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();Properties properties = new Properties();// 指定要处理的异常与视图properties.setProperty("java.lang.NullPointerException", "error");simpleMappingExceptionResolver.setExceptionMappings(properties);resolvers.add(simpleMappingExceptionResolver);}
在Controller中抛出指定的异常:
/*** 使用SimpleMappingExceptionResolver处理异常** @return*/
@GetMapping("e5")
public String exception5() {if(true) {throw new NullPointerException();}return "success";
}
这样就会跳到指定的视图error.jsp页面。
自定义HandlerExceptionResolver
如果觉得SpringMVC提供的异常处理不满足需求,可以实现HandlerExceptionResolver接口自定义异常处理。
package com.morris.spring.mvc.exception;import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Component
public class MyHandlerExceptionResolver extends AbstractHandlerExceptionResolver implements PriorityOrdered {@Overrideprotected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {if(ex instanceof ArrayIndexOutOfBoundsException) {ModelAndView mv = new ModelAndView("error");mv.addObject("exception", "MyHandlerExceptionResolver");return mv;}return null;}/*** 优先级设置高一点,否则会被@ControllerAdvice全局异常处理* @return*/@Overridepublic int getOrder() {return 1;}
}
总结:不管使用上面哪种异常处理方法,只能处理在请求到达了DispatcherServlet,并且出现了异常后进入processDispatchResult()方法。
下面的这两种异常场景不适用:
- 请求没有到达DispatcherServlet的核心流程,如在filter中抛出异常。
- 请求进入processDispatchResult()方法处理异常,但是在处理过程中有抛出了异常,如在@ControllerAdvice方法中抛出了异常。
源码分析
HandlerExceptionResolverComposite的调用过程
在处理controller的返回结果时,发现有异常就会调用异常处理的逻辑:
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
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,@Nullable Object handler, Exception ex) throws Exception {// Success and error responses may use different content typesrequest.removeAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);// Check registered HandlerExceptionResolvers...ModelAndView exMv = null;if (this.handlerExceptionResolvers != null) {/*** handlerExceptionResolvers什么时候初始化的?* @see DispatcherServlet#initHandlerExceptionResolvers(org.springframework.context.ApplicationContext)** @see AbstractHandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)* @see HandlerExceptionResolverComposite#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)*/for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {exMv = resolver.resolveException(request, response, handler, ex);if (exMv != null) {break;}}}if (exMv != null) {if (exMv.isEmpty()) {request.setAttribute(EXCEPTION_ATTRIBUTE, ex);return null;}// We might still need view name translation for a plain error model...if (!exMv.hasView()) {String defaultViewName = getDefaultViewName(request);if (defaultViewName != null) {exMv.setViewName(defaultViewName);}}if (logger.isTraceEnabled()) {logger.trace("Using resolved error view: " + exMv, ex);}else if (logger.isDebugEnabled()) {logger.debug("Using resolved error view: " + exMv);}WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());return exMv;}throw ex;
}
handlerExceptionResolvers何时被初始化的?
org.springframework.web.servlet.DispatcherServlet#initHandlerExceptionResolvers
private void initHandlerExceptionResolvers(ApplicationContext context) {this.handlerExceptionResolvers = null;if (this.detectAllHandlerExceptionResolvers) {/*** HandlerExceptionResolver在WebMvcConfigurationSupport中注入了*/// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerExceptionResolvers = new ArrayList<>(matchingBeans.values());// We keep HandlerExceptionResolvers in sorted order.AnnotationAwareOrderComparator.sort(this.handlerExceptionResolvers);}}else {try {HandlerExceptionResolver her =context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);this.handlerExceptionResolvers = Collections.singletonList(her);}catch (NoSuchBeanDefinitionException ex) {// Ignore, no HandlerExceptionResolver is fine too.}}// Ensure we have at least some HandlerExceptionResolvers, by registering// default HandlerExceptionResolvers if no other resolvers are found.if (this.handlerExceptionResolvers == null) {// 默认ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolverthis.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);if (logger.isTraceEnabled()) {logger.trace("No HandlerExceptionResolvers declared in servlet '" + getServletName() +"': using default strategies from DispatcherServlet.properties");}}
}
handlerExceptionResolvers是从在SpringMVC容器中获取所有的HandlerExceptionResolver实例,那么这些实例是什么时候注入的呢?
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#handlerExceptionResolver
@Bean
public HandlerExceptionResolver handlerExceptionResolver(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();configureHandlerExceptionResolvers(exceptionResolvers);if (exceptionResolvers.isEmpty()) {// 添加默认的HandlerExceptionResolveraddDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);}extendHandlerExceptionResolvers(exceptionResolvers);HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();composite.setOrder(0);composite.setExceptionResolvers(exceptionResolvers);return composite;
}protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers,ContentNegotiationManager mvcContentNegotiationManager) {// 添加ExceptionHandlerExceptionResolverExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();exceptionHandlerResolver.setContentNegotiationManager(mvcContentNegotiationManager);exceptionHandlerResolver.setMessageConverters(getMessageConverters());exceptionHandlerResolver.setCustomArgumentResolvers(getArgumentResolvers());exceptionHandlerResolver.setCustomReturnValueHandlers(getReturnValueHandlers());if (jackson2Present) {exceptionHandlerResolver.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice()));}if (this.applicationContext != null) {exceptionHandlerResolver.setApplicationContext(this.applicationContext);}exceptionHandlerResolver.afterPropertiesSet();exceptionResolvers.add(exceptionHandlerResolver);// 添加ResponseStatusExceptionResolverResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();responseStatusResolver.setMessageSource(this.applicationContext);exceptionResolvers.add(responseStatusResolver);// 添加DefaultHandlerExceptionResolverexceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
默认注册了三个HandlerExceptionResolver:
- ExceptionHandlerExceptionResolver
- ResponseStatusExceptionResolver
- DefaultHandlerExceptionResolver
我们可以通过实现WebMvcConfigurer接口extendHandlerExceptionResolvers()方法注入自己的HandlerExceptionResolver,也可以通过向SpringMVC容器中注入HandlerExceptionResolver实例。
最后ExceptionHandlerExceptionResolver、ResponseStatusExceptionResolver、DefaultHandlerExceptionResolver以及通过实现WebMvcConfigurer接口的extendHandlerExceptionResolvers()方法注入的HandlerExceptionResolver都会包装到HandlerExceptionResolverComposite中。
最后异常处理都会调用HandlerExceptionResolverComposite#resolveException
org.springframework.web.servlet.handler.HandlerExceptionResolverComposite#resolveException
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {if (this.resolvers != null) {for (HandlerExceptionResolver handlerExceptionResolver : this.resolvers) {/*** @see AbstractHandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)*/ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex);if (mav != null) {return mav;}}}return null;
}
然后会调用各个HandlerExceptionResolver的doResolveException()进行异常处理。
org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver#resolveException
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {if (shouldApplyTo(request, handler)) {prepareResponse(ex, response);/*** @see DefaultHandlerExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)* @see ResponseStatusExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)* @see SimpleMappingExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)* @see AbstractHandlerMethodExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)**/// 让所有的ExceptionResolver按顺序挨个处理,有视图返回就救赎ModelAndView result = doResolveException(request, response, handler, ex);if (result != null) {// Print debug message when warn logger is not enabled.if (logger.isDebugEnabled() && (this.warnLogger == null || !this.warnLogger.isWarnEnabled())) {logger.debug("Resolved [" + ex + "]" + (result.isEmpty() ? "" : " to " + result));}// Explicitly configured warn logger in logException method.logException(ex, request);}return result;}else {return null;}
}
ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver从名字就可以看出是处理@ExceptionHandler注解的。
首先看下ExceptionHandlerExceptionResolver的afterPropertiesSet方法,主要解析@ControllerAdvice注解的类中的带有@ExceptionHandler的方法,建议异常与方法之间的映射关系,注意这里只解析了@ControllerAdvice注解的类中的带有@ExceptionHandler注解的方法,并没有解析Controller中带有ExceptionHandler注解的方法。
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#afterPropertiesSet
public void afterPropertiesSet() {// Do this first, it may add ResponseBodyAdvice beans// 解析带有@ControllerAdvice注解的类initExceptionHandlerAdviceCache();if (this.argumentResolvers == null) {List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);}if (this.returnValueHandlers == null) {List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);}
}private void initExceptionHandlerAdviceCache() {if (getApplicationContext() == null) {return;}// 从容器中查找所有带有ControllerAdvice注解的类List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext());for (ControllerAdviceBean adviceBean : adviceBeans) {Class<?> beanType = adviceBean.getBeanType();if (beanType == null) {throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean);}// 解析类中带有@ExceptionHandler的方法ExceptionHandlerMethodResolver resolver = new ExceptionHandlerMethodResolver(beanType);if (resolver.hasExceptionMappings()) {this.exceptionHandlerAdviceCache.put(adviceBean, resolver);}if (ResponseBodyAdvice.class.isAssignableFrom(beanType)) {this.responseBodyAdvice.add(adviceBean);}}if (logger.isDebugEnabled()) {int handlerSize = this.exceptionHandlerAdviceCache.size();int adviceSize = this.responseBodyAdvice.size();if (handlerSize == 0 && adviceSize == 0) {logger.debug("ControllerAdvice beans: none");}else {logger.debug("ControllerAdvice beans: " +handlerSize + " @ExceptionHandler, " + adviceSize + " ResponseBodyAdvice");}}
}
ExceptionHandlerExceptionResolver对异常的处理就是找到@ExceptionHandler注解的方法,并进行反射调用。
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) {// 不管是Controller中的@ExceptionHandler,还是ControllerAdvice中的@ExceptionHandler// 最终异常的处理都是要找到带有@ExceptionHandler注解的方法进行调用ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);if (exceptionHandlerMethod == null) {return null;}if (this.argumentResolvers != null) {exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if (this.returnValueHandlers != null) {exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}ServletWebRequest webRequest = new ServletWebRequest(request, response);ModelAndViewContainer mavContainer = new ModelAndViewContainer();try {if (logger.isDebugEnabled()) {logger.debug("Using @ExceptionHandler " + exceptionHandlerMethod);}Throwable cause = exception.getCause();if (cause != null) {// Expose cause as provided argument as wellexceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod);}else {// Otherwise, just the given exception as-isexceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, handlerMethod);}}catch (Throwable invocationEx) {// Any other than the original exception (or its cause) is unintended here,// probably an accident (e.g. failed assertion or the like).if (invocationEx != exception && invocationEx != exception.getCause() && logger.isWarnEnabled()) {logger.warn("Failure in @ExceptionHandler " + exceptionHandlerMethod, 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;}
}@Nullable
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(@Nullable HandlerMethod handlerMethod, Exception exception) {Class<?> handlerType = null;if (handlerMethod != null) {// Local exception handler methods on the controller class itself.// To be invoked through the proxy, even in case of an interface-based proxy.handlerType = handlerMethod.getBeanType();ExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(handlerType);if (resolver == null) {// 解析controller中带有@ExceptionHandler注解的方法resolver = new ExceptionHandlerMethodResolver(handlerType);this.exceptionHandlerCache.put(handlerType, resolver);}// 根据异常找到@ExceptionHandler注解的方法Method method = resolver.resolveMethod(exception);if (method != null) {return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method);}// For advice applicability check below (involving base packages, assignable types// and annotation presence), use target class instead of interface-based proxy.if (Proxy.isProxyClass(handlerType)) {handlerType = AopUtils.getTargetClass(handlerMethod.getBean());}}// 这里@ControllerAdvice全局异常的处理// exceptionHandlerAdviceCache属性在afterProperties()方法中初始化for (Map.Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry : this.exceptionHandlerAdviceCache.entrySet()) {ControllerAdviceBean advice = entry.getKey();if (advice.isApplicableToBeanType(handlerType)) {ExceptionHandlerMethodResolver resolver = entry.getValue();// 根据异常找到@ExceptionHandler注解的方法Method method = resolver.resolveMethod(exception);if (method != null) {return new ServletInvocableHandlerMethod(advice.resolveBean(), method);}}}return null;
}
ResponseStatusExceptionResolver
ResponseStatusExceptionResolver主要是要拿到异常类上面的@ResponseStatus注解,然后将response的状态和内容设置为@ResponseStatus注解中的内容。
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#doResolveException
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {try {if (ex instanceof ResponseStatusException) {return resolveResponseStatusException((ResponseStatusException) ex, request, response, handler);}// 拿到异常上面的@ResponseStatus注解ResponseStatus status = AnnotatedElementUtils.findMergedAnnotation(ex.getClass(), ResponseStatus.class);if (status != null) {// 设置错误码和错误内容return resolveResponseStatus(status, request, response, handler, ex);}if (ex.getCause() instanceof Exception) {return doResolveException(request, response, handler, (Exception) ex.getCause());}}catch (Exception resolveEx) {if (logger.isWarnEnabled()) {logger.warn("Failure while trying to resolve exception [" + ex.getClass().getName() + "]", resolveEx);}}return null;
}
DefaultHandlerExceptionResolver
DefaultHandlerExceptionResolver是用来处理spring mvc内部异常,如HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException等异常。
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {// 处理spring内部异常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;
}
SimpleMappingExceptionResolver
我们在构造SimpleMappingExceptionResolver时就会指定异常与视图的映射关系,在处理异常时只需要在映射map中获取即可。
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {// Expose ModelAndView for chosen error view.// 将异常与属性exceptionMappings、excludedExceptions进行匹配,拿到视图名称String viewName = determineViewName(ex, request);if (viewName != null) {// Apply HTTP status code for error views, if specified.// Only apply it if we're processing a top-level request.Integer statusCode = determineStatusCode(request, viewName);if (statusCode != null) {applyStatusCodeIfPossible(request, response, statusCode);}return getModelAndView(viewName, ex, request);}else {return null;}
}protected String determineViewName(Exception ex, HttpServletRequest request) {String viewName = null;if (this.excludedExceptions != null) {// 与传入的异常的类型进行匹配for (Class<?> excludedEx : this.excludedExceptions) {if (excludedEx.equals(ex.getClass())) {return null;}}}// Check for specific exception mappings.if (this.exceptionMappings != null) {// 与传入的异常的名字进行匹配viewName = findMatchingViewName(this.exceptionMappings, ex);}// Return default error view else, if defined.if (viewName == null && this.defaultErrorView != null) {if (logger.isDebugEnabled()) {logger.debug("Resolving to default view '" + this.defaultErrorView + "'");}viewName = this.defaultErrorView;}return viewName;
}
【springmvc】九大组件之HandlerExceptionResolver相关推荐
- springMVC九大组件及一次请求流程
一.九大组件 HandlerMapping(处理器映射器) HandlerMapping 是⽤来查找Handler的,也就是处理器,具体的表现形式可以是类,也可以是⽅法.⽐如,标注了@RequestM ...
- springmvc十六:九大组件
DispatcherServlet中有九个引用类型的属性,这就是springmvc的九大组件. springmvc在工作的时候,关键位置都是由这些组件完成的. /** MultipartResolve ...
- Openstack九大组件
云是服务 云,本身没有资源,只是去管理和调度资源 虚拟化是技术 虚拟化提供资源,在云的世界里,虚拟化提供底层的计算.存储.网络资源,由云来接管 云的五大特征: 按需自助服务 广泛的网络接入 资源池化 ...
- 一个字稳,云原生产品家族支撑冬奥会九大业务场景,打造云上奥运新体验
北京冬奥会已经成为收视最高的一届冬奥会,在转播时长.技术.内容制作方式等多方面都书写了新记录.云技术的应用,是本届北京冬奥会赛事转播的一大特色. 而云原生作为云计算的新界面,如何稳定支撑北京冬奥会多个 ...
- 避免踩坑:易盾安全老司机起底Android九大漏洞,附解决建议
Android应用会遇到各种各样的漏洞,如何从细节上了解各种安全隐患,积极采取适当的防御措施便变得尤为重要.为了让大家对Android漏洞有一个非常全面的认识,网易云易盾资深安全工程师徐从祥为大家详细 ...
- 《微服务》九大特性重读笔记
今天重读了Martin Fowler的<Microservices>,在此记录一下对九大特性的理解. 服务组件化 组件,是一个可以独立更换和升级的单元.就像PC中的CPU.内存.显卡.硬盘 ...
- Linux 系统日常运维九大技能和运维网络知识总结
一.Linux 系统日常运维九大技能 1.安装部署 方式:U盘,光盘和网络安装 其中网络安装已经成为了目前批量部署的首选方式:主要工具有Cobbler和PXE+kickstart 可以参考如下链接内容 ...
- 未来中国智能制造九大趋势
智能制造(Intelligent Manufacturing,IM)是一种由智能机器和人类专家共同组成的人机一体化智能系统,它在制造过程中能进行智能活动,诸如分析.推理.判断.构思和决策等.它包含智能 ...
- 专题 | 项目管理知识、方法论、工具NO.9:你应该知道的项目管理的五个过程组和九大知识领域
我们都想做一个优秀的项目经理,但是很多项目经理常陷入问题的泥淖中出不来.计划有问题.人员能力不足.进度赶不上.质量不达标.客户不满意,项目开始不到一个月,项目经理被各种问题缠的透不过气来,自己乱了阵脚 ...
最新文章
- 三态门有一个信号控制端en_W25Q32JVSSIQ|哪些PCB设计会影响信号质量?
- linux创建隐藏进程6,在Linux 2.6内核下实现进程隐藏
- 互联网性能与容量评估的方法论和典型案例
- leetcode 上的Counting Bits 总结
- 灵魂拷问:你和大佬,技术差距有多大?
- TCP三次握手及四次挥手详细图解(转)
- Qt工作笔记-使用QGraphicsItem绘制复杂的图形
- linux 系统内如何查看当前CPU详细信息
- php token 表单重复提交,PHP生成token防止表单重复提交2个例子
- Combobox绑定数据源DataSet
- Mybatis与JDBC的对比超详细笔记
- 如何用axure绘制图表_用Python绘制手绘风格的图表
- 比Google Map更加清晰的网络地图——RealBird
- ant组件中select默认选中某一项
- Aurora使用教程 第一讲
- Android使用Github Actions持续集成并自动上传apk到蒲公英App内测分发平台(含证书密码脱敏)
- 微信小程序项目实例——食堂吃哪个
- define和sbit的区别
- 【Mac 教程系列第 16 篇】如何查看 Apple 产品的真伪
- 抖音影视解说制作,一般用什么必备工具?