想弄清楚Spring MVC如何工作主要看DispatcherServlet核心控制器:
在使用Java方式配置DispatcherServlet时,只需要扩展AbstractAnnotationConfigDispatcherServlet的任意类都
会自动地配置DispatcherServlet和Spring应用上下文,Spring的应用上下文位于应用程序的Servlet上下文中。
在Servlet3.0环境中容器会在类路径下查找实现javax.servlet.ServletContainerInitializer接口的类。
Spring提供了该接口的实现类SpringServletContainerInitializer,该类则反过来查找实现
org.springframework.web.WebApplicationInitializer接口的类并将配置的任务交给他们来完成。
Spring3.2引入了一个WebApplicationInitializer的基础实现:
org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer
扩展该类重写其方法来创建 两个应用上下文:
一个是由DispatcherServlet创建的应用上下文,
加载包含Web组件的bean,如:控制器、视图解析器、处理器映射器。
另一个是由ContextLoaderListener创建的应用上下文,
加载应用中的其他bean,如:驱动应用后端的中间层和数据层组件。
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
/**
* 此方法返回的带有@Configuration注解的类将会用来配置ContextLoaderListener创建的应用上下文中的Bean
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
/**
* 由DispatcherServlet创建的应用上下文,加载包含Web组件的bean,使用定义在WebConfig配置类中的Bean。
*
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
/**
* 配置路径映射
*/
@Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
DispatcherServlet继承了HttpServlet,在Servlet的init方法调用时来执行SpringMVC的初始化工作。
初始化内容如下:
//初始化策略,完成SpringMVC默认实现类的初始化,onRefresh是在父类FrameworkServlet中调用
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
//处理文件上传,SpringBoot中默认使用StandardServletMultipartResolver
initMultipartResolver(context);
//处理国际化问题,如字符编码问题
initLocaleResolver(context);
//定义一个主题,如:设置用户访问的页面样式
initThemeResolver(context);
//定义用户设置的请求映射关系,把URL映射成Handler实例
initHandlerMappings(context);
//根据Handler类型定义不同的处理规则
initHandlerAdapters(context);
//对Handler进行统一的出错处理,默认实现类是SimpleMappingExceptionResolver
initHandlerExceptionResolvers(context);
//将ViewName替换成其他格式,如加前后缀
initRequestToViewNameTranslator(context);
//初始化视图解析器,将View解析成页面,默认为InternalResourceViewResolver,按照JSP页面解析
initViewResolvers(context);
//初始化与链接跳转相关的FlashMapManager
initFlashMapManager(context);
}