前端控制器DispatcherServlet拦截请求之后做了什么工作呢?DispatcherServlet又是如何分派请求的呢?
我们来根据DispatcherServlet的源代码分析一下,源代码如下:
protected void initStrategies(ApplicationContext context) {
// 初始化上传文件解析器
initMultipartResolver(context);
// 初始化本地化解析器
initLocaleResolver(context);
// 初始化主题解析器
initThemeResolver(context);
// 初始化处理器骑射器,将请求映射到处理器
initHandlerMappings(context);
// 初始化处理器适配器
initHandlerAdapters(context);
// 初始化处理器异常解析器,如果执行过程中遇到异常将交给HandlerExceptionResolver来解析
initHandlerExceptionResolvers(context);
// 初始化请求到视图名称解析器
initRequestToViewNameTranslator(context);
// 初始化视图解析器,通过ViewResolver解析逻辑视图名到具体视图实现
initViewResolvers(context);
// 初始化flash映射管理器
initFlashMapManager(context);
}
initStrategies方法将在WebApplicationContext初始化后自动执行,自动扫描上下文的Bean,根据名称或类型匹配的机制查找自定义的组件,如果没有找到则会装配一套Spring的默认组件。在`org.springframework.web.servlet` 路径下有一个DispatcherServlet.properties配置文件,该文件指定了DispatcherServlet所使用的默认组件。
//本地化解析器
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
//主题解析器
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
//处理器映射器(共2个)
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
//处理器适配器(共3个)
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
//异常处理器(共3个)
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
//视图名称解析器
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
//视图解析器
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
//FlashMap映射管理器
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
如果开发者希望使用自定义类型的组件,则只需要在Spring配置文件中配置自定义的Bean组件即可。Spring MVC如果发现上下文中有用户自定义的组件,就不会使用默认的组件。
以下是DispatcherServlet装配每种组件的细节。
本地化解析器。只允许一个实例
(1)查找名为localeResolver、类型为.LocaleResolver的Bean作为该类型组件。
(2)如果没有找到,则使用默认的实现类AcceptHeaderLocaleResolver作为该类型组件。
主题解析器。只允许一个实例。
(1)查找名为themeResolver、类型为ThemeResolver的Bean作为该类型的组件。
(2)如果没有找到,则使用默认的实现类FixedThemeResolver作为该类型组件。
处理器映射器。允许多个实例
(1)如果detectAllHandlerMappings的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为HandlerMapping的Bean,将它们作为该类型组件。
(2)如果detectAllHandlerMappings的属性为fales,则查找名为handlerMappings、类型为HandlerMapping的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则使用BeanNameUrlHandlerMapping实现类创建该类型的组件。
处理器适配器。允许多个实例
(1)如果detectAllHandlerAdapters属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为HandlerAdapter的Bean,将它们作为该类型组件。
(2)如果detectAllHandlerAdapters的属性为false,则查找名为handlerAdapter、类型为HandlerAdapter的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则使用DispatcherServlet.properties配置文件中指定的三个实现类分别创建一个适配器,并将其添加到适配器列表中。
处理器异常解析器。允许多个实例
(1)如果detectAllHandlerExceptionResolvers的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为HandlerExceptionResolver的Bean,将它们作为该类型组件。
(2)如果detectAllHandlerExceptionResolver的属性为false,则查找名为handlerExceptionResolver、类型为HandlerExceptionResolver的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则查找DispatcherServlet.properties配置文件中定义的默认实现类,注意,该文件中没有对应处理器异常解析器的默认实现类,用户可以自定义处理器异常解析器的实现类,将之添加到DispatcherServlet.properties配置文件当中。
视图名称解析器。只允许一个实例
(1)查找名为viewNameTranslator、类型为RequestToViewNameTranslator的Bean作为该类型组件。
(2)如果没有找到,则使用默认的实现DefaultRequestToViewNameTranslator作为该类型的组件。
视图解析器。允许多个实例
(1)如果detectAllViewResolver的属性为true(默认为true),则根据类型匹配机制查找上下文以及Spring容器中所有类型为ViewResolver的Bean,将它们作为该类型组件。
(2)如果detectAllViewResolver的属性为false,则查找名为viewResolvers、类型为ViewResolver的Bean作为该类型组件。
(3)如果通过以上两种方式都没有找到,则查找DispatcherServlet.properties配置文件中定义的默认实现类InternalResolverViewResolver作为该类型的组件。
文件上传解析器。只允许一个实例
(1)查找名为muliipartResolver、类型为MuliipartResolver的Bean作为该类型组件。
(2)如果用户没有在上下文中显式定义MuliipartResolver类型的自己,则DispatcherServlet将不会加载该类型的组件。
FlashMap映射管理器。
(1)查找名为FlashMapManager、类型为SessionFlashMapManager的Bean作为该类型组件,用于管理FlashMap,即数据默认存储在HttpSession中。
如果同一类型的组件存在多个,那么它们之间的优先级顺序如何确定呢?因为这些组件都实现了org.springFramework.core.Ordered接口,所以可以通过Order属性确定优先级的顺序,值越小的优先级越高。