一、web.xml配置
<!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>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
入口分析
我们知道,在单独使用springmvc(不加入spring-context等组件)的时候,我们需要配置DispatcherServlet,那它是如何工作的呢,入口在哪?
通过查看DispatcherServlet,我们知道它实质是一个servlet,tomcat容器的启动(我们假设是用的tomcat),会启动我们的Servlet,执行init方法。
(注:DispatcherServlet继承了HttpServletBean,于是接下来我们就从init方法往下捋)
下面是代码执行步骤,也就是springmvc的执行流程
HttpServletBean.init();//初始化方法
FrameworkServlet.initServletBean();//初始化servlcet对象
initWebApplicationContext
FrameworkServlet.createWebApplicationContext(rootContext);//创建上下文
FrameworkServlet.onRefresh(wac)-->DispatcherServlet.onRefresh(wac)
DispatcherServlet.initStrategies(context);//初始化各种解析器(上传文件,国际化,映射器,适配器,日志等)
DispatcherServlet.doService(request, response);//处理请求
DispatcherServlet.doDispatch(request, response);//分发请求
getHandler(processedRequest);//处理器映射器
this.getHandlerAdapter(mappedHandler.getHandler());//处理器适配器
ha.handle(...)//执行处理器逻辑
applyDefaultViewName(processedRequest, mv);//视图渲染
二、和spirng融合
(注:上面是没有和spring融合,如果在ssm或者ssh的项目中)
我们在web.xml配置文件那里还会配置 ContextLoaderListener
文件如下
<!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>
<display-name>Archetype Created Web Application</display-name>
<!-- 配置启动 Spring IOC 容器的 Listener -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
初始化默认加载XmlWebApplicationContext根上下文
ContextLoaderListener.contextInitialized
->
ContextLoaderListener.initWebApplicationContext->
ContextLoaderListener.determineContextClass(sc);
->
defaultStrategies.getProperty(...)
->
ContextLoader.properties文件
ContextLoader.properties文件
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
protected Class<?> determineContextClass(ServletContext servletContext) {
// 若你在web.xml中设置的<context-param>里声明了
// contextClass的值,则直接利用反射得到其Class
String contextClassName = servletContext.getInitParameter("contextClass");
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
} catch (ClassNotFoundException var4) {
throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", var4);
}
} else {
// 这里返回XmlWebApplicationContext
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
// 反射得到XmlWebApplicationContext.Class
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
} catch (ClassNotFoundException var5) {
throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", var5);
}
}
}
把spring容器作为父容器
在 DispatcherServlet 中也会创建一个 WebApplicationContext 我们称之为 子上下文,当执行dispatchServlet的创建上下文方法时,会把根容器上下文作为自己的父容器
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
if (!cwac.isActive()) {
//把根容器上下文放入自己的上下文容器中,所以我们把springmvc的容器称之为子容器
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
}
本文为本人总结的springmvc源码的流程,如果对您起动了一点点的帮助,请在下面点个小小的赞,将是对本人的很大鼓励!非常感谢
本文如有错误之处,望不吝指出,谢谢。