一.概述
1. springMVC的核心是DispatcherServlet,它负责截获请求并将其分派给相对应的处理器处理。
2. DispatcherServlet说到底是个Servlet,有init(ServletConfig)、service()、destroy()等方法:
- 服务器启动时会创建DispatcherServlet实例,这时DispatcherServlet实例还是只是一个普通对象
- 触发init(ServletConfig)方法,使DispatcherServlet实例变成一个真正的Servlet,在init(ServletConfig)调用init()初始化一些东西
- DispatcherServlet的父类HttpServletBean重写的init()方法,初始化Spring MVC配置文件/WEB-INF/spring/applicationContext.xml的信息
- 客户请求到来触发service()方法,DispatcherServlet实例负责分发请求到不同的控制器
二.初始化DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- 配置Spring Bean定义文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
<!-- Spring初始化监听器:web应用启动时,监听器初始化Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 初始化<span style="font-family: tahoma, arial, 宋体;">spring前端控制器</span>DispatcherServlet -->
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/*.do</url-pattern>
</servlet-mapping>
</web-app>
2.1 web服务器启动DispatcherServlet
初始化DispatcherServlet实例
public DispatcherServlet() {
super();
}
2.2 调用Servlet的init(ServletConfig)
2.1中只是创建了一个普通的对象,DispatcherServlet要变成一个真正的Servlet,还需要执行init(ServletConfig)方法// javax.servlet.GenericServlet
public void init(ServletConfig config throws ServletException {
this.config = config;
init();
}
子类重写init()方法,加载DispatcherServlet的init-param初始化参数
// org.springframework.web.servlet.HttpServletBean
@Override
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
// Set bean properties from init parameters.
try {
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
}
// Let subclasses do whatever initialization they like.
initServletBean();
if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}
子类重写initServletBean()方法,创建DispatcherServlet实例的上下文WebApplicationContext
// org.springframework.web.servlet.FrameworkServlet
@Override
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();
try {
// 创建上下文
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
catch (ServletException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " + elapsedTime + " ms");
}
}
2.3 调用initStrategies()
initStrategies()方法将在DispatcherServlet对应的上下文WebApplicationContext初始化后自动执行,此时Spring上下文中的Bean已经初始化完成,该方法的工作是通过反射机制查找并装配Spring上下文中显示定义的组件Bean,如果找不到就装配默认的组件实例。
// org.springframework.web.servlet.DispatcherServlet
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
// 初始化上传文件的解析器
initMultipartResolver(context);
// 初始化本地化解析器
initLocaleResolver(context);
// 初始化主题解析器
initThemeResolver(context);
// 初始化处理器器
initHandlerMappings(context);
// 初始化处理器适配器
initHandlerAdapters(context);
// 初始化处理异常的解析器
initHandlerExceptionResolvers(context);
// 初始化请求到视图名的翻译器
initRequestToViewNameTranslator(context);
// 初始化视图的解析器
initViewResolvers(context);
initFlashMapManager(context);
}
Spring MVC定义了一套默认的组件实现类,即没有显示定义组件Bean,DispatcherServlet就装配默认组件,默认组件配置位置:
// org.springframework.web.servlet.DispatcherServlet.DispatcherServlet.properties
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
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
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager