前言
Spring mvc 的实现我们主要分两个阶段来了解,一个是初始化阶段,一个是调用阶段,在了解mvc之前,可以先了解一下servlet的生命周期
servlet生命周期包括init一次,service多次,destroy一次
而我们下面要了解的mvc初始化阶段,核心就是DispatcherServlet
mvc初始化阶段
来看DispatcherServlet
DispatcherServlet
我们需要找到的是servlet的init方法真正的实现位置,即HttpServletBean的init方法
HttpServletBean
该方法首先将配置参数映射到此servlet的bean属性上,紧接着调用子类初始化。
我们来看子类初始化做了啥事情
FrameworkServlet
DispatcherServlet继承了FrameworkServlet,而FrameworkServlet继承了HttpServletBean并重写了initServletBean
/**
* Overridden method of {@link HttpServletBean}, invoked after any bean properties
* have been set. Creates this servlet's WebApplicationContext.
*/
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
if (logger.isInfoEnabled()) {
logger.info("Initializing Servlet '" + getServletName() + "'");
}
long startTime = System.currentTimeMillis();
try {
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException | RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
if (logger.isDebugEnabled()) {
String value = this.enableLoggingRequestDetails ?
"shown which may lead to unsafe logging of potentially sensitive data" :
"masked to prevent unsafe logging of potentially sensitive data";
logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
"': request parameters and headers will be " + value);
}
if (logger.isInfoEnabled()) {
logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
}
}
该方法首先是初始化了spring web容器,webApplicationContext,关于容器,请看spring容器,初始化后,会触发ContextRefreshedEvent事件,调用onRefresh初始化三大件,关于ContextRefreshedEvent,可以参考ContextRefreshedEvent
onRefresh
该方法便是初始化mvc九大件的实际入口
/**
* 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) {
initMultipartResolver(context); //用于处理文件上传
initLocaleResolver(context); // 主要作用在于根据不同的用户区域展示不同的视图
initThemeResolver(context); // 主题就是系统的整体样式或风格,可通过Spring MVC框架提供的主题(theme)设置应用的整体样式风格,提高用户体验。Spring MVC的主题就是一些静态资源的集合,即包括样式及图片,用来控制应用的视觉风格。
/**
*用来查找Handler的。在SpringMVC中会有很多请求,每个请求都需要一个Handler处理,具体接收到一个请求之后使用哪个Handler进行处理呢?这就是HandlerMapping需要做的事。
*作用是根据当前请求的找到对应的 Handler,并将 Handler(执行程序)与一堆 HandlerInterceptor(拦截器,也是它来处理的)封装到 HandlerExecutionChain 对象中,返回给中央调度器。
**/
initHandlerMappings(context);
/**
*因为SpringMVC中的Handler可以是任意的形式,只要能处理请求就ok,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法。如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情。
**/
initHandlerAdapters(context);
// 对异常情况进行处理
initHandlerExceptionResolvers(context);
// Spring MVC是通过ViewName来找到对应的视图的,而此接口的作用就是从request中获取viewName。
initRequestToViewNameTranslator(context);
/**
*ViewResolver用来将String类型的视图名和Locale解析为View类型的视图。View是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其它类型)文件。这里就有两个关键问题:使用哪个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要要做的工作。
*ViewResolver需要找到渲染所用的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成。
**/
initViewResolvers(context);
// 用来管理FlashMap的,FlashMap主要用在redirect中传递参数。
initFlashMapManager(context);
}
关于九大件可以,参考一下mvc九大件
Handler是用来干活的工具;HandlerMapping用于根据需要干的活找到相应的工具;HandlerAdapter是使用工具干活的人