Spring 启动包括几个步骤
我们看下配置文件
<serlvet>
<servlet-name>spring</servlet-name>
<servlet-class>org.srpingframework.web.servlet.DispatcherServlet</servlet-class>
<load-startup>2</load-startup>
</serlvet>
<serlvet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfiguration</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframwork.web.context.ContextLoaderListener
</listener-class>
</listener>
从配置文件,我们可以看到一个监听器和 DispatcherSerlvet
。监听器负责在 Web 容器中建立起双亲 IOC 容器,另一个生成相应的 WebApplicationContext
并将其初始化。
然后 DispatcherServlet
的父类 FramworkServlet
中进行获取刚刚 ContextLoderListener
已经加载好的 IOC 容器。然后交给了 DispacherServlet
进行 getBean()
。
Spring MVC 请求的过程是什么?
首先我们知道了在 web.xml
上,我们用 DispatcherServlet
拦截了所有请求。而其实 DispatcherServlet
也是一个 Servlet
。这里有一个这样的继承图:
graph LR
DispatcherServlet-->FrameworkServlet
FrameworkServlet-->HttpServletBean
HttpServletBean-->HttpServlet
HttpServlet-->GenericServlet
Spring MVC 整个框架初始化在哪里?
在 DispatcherServlet
的 initStrategies
方法中。
protected void initStrategies(ApplicationContext context) {
this.initMultipartResolver(context);
// 国际化
this.initLocaleResolver(context);
// 适配器
this.initThemeResolver(context);
// 请求映射
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
// 异常
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
// 视图
this.initViewResolvers(context);
this.initFlashMapManager(context);
}
这里有初始化媒体的上传组件、国际化 localResovler
、支持 request
的映射 requestMapping
等等。在这里加载是因为方便 DispatcherServlet
进行操作。
DispatcherServlet 真正开始分发的位置在哪里?
前面说了,其实 DispatcherServlet
是一个 servlet
,所以它的 doService
方法是拦截所有请求的地方。
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 进行一些前置处理
...
try {
// 开始分发
this.doDispatch(request, response);
} finally {
// 进行一些后置处理
...
}
}
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
// 检查是不是图片或其他文件上传的请求
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 获取相应的 HandlerExecutionChain(其实这个 HandlerExecutionChain 封装了请求的 controller 和 相应的拦截器)
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
// 交付给相应的 Adapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (this.logger.isDebugEnabled()) {
this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
return;
}
}
// 调用相关的请求之前的拦截器
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 使用 Adapter 开始处理请求并返回视图。记住,Adapter 才是真正进行处理的流程。
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 生成以请求的路径为视图名
this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}