SSM-SpringMVC-SpringMVC初始化-初始化映射请求上下文
映射请求上下文是通过DispatcherServlet初始化的,根据自己的需要配置启动时初始化,或者等待用户第一次请求时进行初始化。在WEB工程中没有注册ContextLoaderListener,这时DispatcherServle就会在其初始化对SpringIOC进行初始化
选择什么时候初始化:
大部分情况下,让DispatcherServle在服务器启动期间就完成SpringIoc容器初始化,可以在WEB容器刚开始就对其初始化,在整个WEB的初始化中,不只是DispatcherServle需要得到SpringIOC资源,其他组件也需要,因此大部分情况下都建议使用ContextLoaderListener进行初始化
DispatcherServle设计:
是一个可以加载加载WEB容器中的Servlet
web容器对于servlet的初始化,首先调用其init初始化方法,对于DispactherServlet也是如此,该方法位于父类HttpServletBean
public final void init() throws ServletException {
PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
//根据参数初始化 bean 的属性
try {
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
this.initBeanWrapper(bw);
bw.setPropertyValues(pvs, true);
} catch (BeansException var4) {
if (this.logger.isErrorEnabled()) {
this.logger.error("Failed to set bean properties on servlet '" + this.getServletName() + "'", var4);
}
throw var4;
}
}
//交由子类去实现
this.initServletBean();
}
上面代码中,可以看到initServletBean方法,在FrameworkServlet类中也能看见该方法,所以它覆盖了FrameworkServlet类中的initServletBean方法。
FrameworkServlet中的initServletBean方法
protected final void initServletBean() throws ServletException {
this.getServletContext().log("Initializing Spring " + this.getClass().getSimpleName() + " '" + this.getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("Initializing Servlet '" + this.getServletName() + "'");
}
long startTime = System.currentTimeMillis();
try {
//初始化SpringIOC容器
this.webApplicationContext = this.initWebApplicationContext();
this.initFrameworkServlet();
} catch (RuntimeException | ServletException var4) {
this.logger.error("Context initialization failed", var4);
throw var4;
}
if (this.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";
this.logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails + "': request parameters and headers will be " + value);
}
if (this.logger.isInfoEnabled()) {
this.logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
}
}
方法initWebApplicationContext:
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
//判断是否已经被初始化
if (this.webApplicationContext != null) {
//如果webIOC容器已经在启动的时候创建,那么久沿用它
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
if (!cwac.isActive()) {
//如果SPirng IOC容器还没有刷新,那么就进行刷新父类容器上下文,设置id等操作
//处理父容器为空的情况
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
//没有被初始化,则查找是否存在的Spring Web IoC容器
if (wac == null) {
wac = this.findWebApplicationContext();
}
//没有初始化,也没有找到存在的Spring Web Ioc容器,则DispatcherServlet自己创建
if (wac == null) {
wac = this.createWebApplicationContext(rootContext);
}
//当onRefresh方法没有被调用过,执行onRefresh方法
if (!this.refreshEventReceived) {
synchronized(this.onRefreshMonitor) {
this.onRefresh(wac);
}
}
if (this.publishContext) {
//作为Servlet的上下文属性发布IOC容器
String attrName = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName, wac);
}
return wac;
}
当IOC容器没有对应初始化,DispatcherServlet会尝试去初始化它,最后调度onRefresh方法,是DispatcherServlet十分关注的方法,该方法就在DispatcherServlet中
onRefresh方法在DispatcherServlet代码中如下:
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
其中调用了自身的initStrategies方法:
protected void initStrategies(ApplicationContext context) {
//初始化文件的解析
this.initMultipartResolver(context);
//本地解析化
this.initLocaleResolver(context);
//主题解析
this.initThemeResolver(context);
//处理器解析
this.initHandlerMappings(context);
//处理器的适配器
this.initHandlerAdapters(context);
//Handler的异常处理解析器
this.initHandlerExceptionResolvers(context);
//当处理器没有返回逻辑视图名等相关信息时,自动将请求 URL 映射为逻辑视图名
this.initRequestToViewNameTranslator(context);
//视图逻辑名称转化器,即允许返回逻辑视图名称,然后它会找到真实的视图
this.initViewResolvers(context);
//这是一个关注Falsh开发的Map管理器
this.initFlashMapManager(context);
}
- MultipartResolver:文件解析器,用于支持服务器的文件上传
- LocaleResolver:国际化解析器,可以提供国际化的功能
- ThemeResolver:主题解析器,类似软件皮肤的转换功能
- HandlerMapping:会 包装用户提供一个控制器的方法和对它的一些拦截,通过调用他就能运行控制器
- handlerAdapter:处理适配器,因为处理器会在不同的上下文运行,SpringMVC会先找到合适的适配器,然后运行处理器服务方法
- HandlerExceptionResolver:处理器异常解析器,当产生异常,可以通过异常解析器来处理
- RequestTo ViewNameTranslator :视图逻辑名称转换器,在控制前中返回一个视图的名称,通过它可以找到实际的视图,当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名
- ViewResolver:视图解析器,当控制器返回后,通过视图解析器会把逻辑视图名称进行解析,然后定位实际视图
器来处理
- RequestTo ViewNameTranslator :视图逻辑名称转换器,在控制前中返回一个视图的名称,通过它可以找到实际的视图,当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名
- ViewResolver:视图解析器,当控制器返回后,通过视图解析器会把逻辑视图名称进行解析,然后定位实际视图
上面是Spring MVC主要的组件的初始化,实际,这些组件DispatcherServlet会根据配置文件DispatcherServlet.properties进行初始化