概述
Spring MVC
的缺省配置类WebMvcConfigurationSupport
定义了一组HandlerExceptionResolver
组件到容器,供Spring MVC
运行时使用,具体来讲,是被DispatcherServlet
使用。本文介绍WebMvcConfigurationSupport
定义了哪些HandlerExceptionResolver
组件,都是什么类型,以及它们的应用目的。
HandlerExceptionResolver
组件定义
WebMvcConfigurationSupport
的bean
定义方法HandlerExceptionResolver handlerExceptionResolver()
用于定义DispatcherServlet
最终使用的一组HandlerExceptionResolver
。该bean
实际类型是HandlerExceptionResolverComposite
,表示多个HandlerExceptionResolver
的组合。
bean
定义方法HandlerExceptionResolver handlerExceptionResolver()
的工作流程基本如下 :
- 创建空的
List<HandlerExceptionResolver> exceptionResolvers
; - 让实现子类提供自定义的
HandlerExceptionResolver
到exceptionResolvers
;
void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers)
- 如果实现子类没有提供自定义
HandlerExceptionResolver
,则添加缺省的HandlerExceptionResolver
到exceptionResolvers
;
final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers)
- 让实现子类增加更多自定义的
HandlerExceptionResolver
到exceptionResolvers
,或者修改exceptionResolvers
内容;
void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers)
- 将所有
List<HandlerExceptionResolver> exceptionResolvers
包装成一个HandlerExceptionResolverComposite
。
缺省情况下,开发人员并不定制和修改exceptionResolvers
,换句话讲,此时exceptionResolvers
中只有以上第三步WebMvcConfigurationSupport
缺省定义的HandlerExceptionResolver
被放到exceptionResolvers
中。
下面我们重点分析一下这个方法。
final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers)
1. addDefaultHandlerExceptionResolvers
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
// 定义一个 ExceptionHandlerExceptionResolver
ExceptionHandlerExceptionResolver 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);
// 定义一个 ResponseStatusExceptionResolver
ResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();
responseStatusResolver.setMessageSource(this.applicationContext);
exceptionResolvers.add(responseStatusResolver);
// 定义一个 DefaultHandlerExceptionResolver
exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
从该方法的实现可以看出,Spring MVC
缺省使用了三个HandlerExceptionResolver
,实现类如下 :
ExceptionHandlerExceptionResolver
ResponseStatusExceptionResolver
DefaultHandlerExceptionResolver
2. 涉及到的HandlerExceptionResolver
实现类
1.ExceptionHandlerExceptionResolver
如果某个HanlderMethod
执行时发生了异常,尝试找到一个使用了@ExceptionHandler
注解的异常处理器将异常转换成ModelAndView
的形式,通常对应到一个错误视图error view
。
2.ResponseStatusExceptionResolver
尝试使用异常上的@ResponseStatus
注解信息将异常翻译成HTTP
状态字。
3.DefaultHandlerExceptionResolver
Spring MVC
缺省异常处理器,最低优先级,将标准Spring MVC
异常翻译成HTTP
状态字。
这些类和所实现的接口HandlerExceptionResolver
之间的关系如下图所示 :
参考文章
Spring MVC 概念模型 – 接口 HandlerExceptionResolver
How Spring Boot Initializes the Spring MVC Application Context