DispatcherServlet的初始化过程
- org.springframework.web.servlet.FrameworkServlet#initServletBean
protected final void initServletBean() throws ServletException {
//...
try {
this.webApplicationContext = this.initWebApplicationContext();
this.initFrameworkServlet();
} catch (RuntimeException | ServletException var4) {
this.logger.error("Context initialization failed", var4);
throw var4;
}
//...
}
- org.springframework.web.servlet.FrameworkServlet#initWebApplicationContext
初始化SpringMVC的IoC容器。
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
//...
if (wac == null) {
//初始化WebApplicationContext(IoC容器)
wac = this.createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
synchronized(this.onRefreshMonitor) {
//刷新WebApplicationContext(IoC容器)
this.onRefresh(wac);
}
}
if (this.publishContext) {
//在应用域内共享WebApplicationContext(IoC容器)
String attrName = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName, wac);
}
return wac;
}
- org.springframework.web.servlet.FrameworkServlet#createWebApplicationContext(org.springframework.context.ApplicationContext)
创建SpringMVC的IoC容器。
protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
Class<?> contextClass = this.getContextClass();
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Fatal initialization error in servlet with name '" + this.getServletName() + "': custom WebApplicationContext class [" + contextClass.getName() + "] is not of type ConfigurableWebApplicationContext");
} else {
//创建IoC容器
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(contextClass);
wac.setEnvironment(this.getEnvironment());
//设置父容器(将Spring的IoC容器设置为SpringMVC的IoC容器的父容器)
wac.setParent(parent);
String configLocation = this.getContextConfigLocation();
if (configLocation != null) {
wac.setConfigLocation(configLocation);
}
this.configureAndRefreshWebApplicationContext(wac);
return wac;
}
}
- org.springframework.web.servlet.DispatcherServlet#onRefresh
刷新SpringMVC的IoC容器。
protected void onRefresh(ApplicationContext context) {
this.initStrategies(context);
}
- org.springframework.web.servlet.DispatcherServlet#initStrategies
初始化策略,即初始化DispatcherServlet的各个组件。
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);
}
DispatcherServlet的服务过程
- javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
this.service(request, response);
} else {
throw new ServletException("non-HTTP request or response");
}
}
- javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
- org.springframework.web.servlet.FrameworkServlet#service
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
super.service(request, response);
} else {
this.processRequest(request, response);
}
}
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected final void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.processRequest(request, response);
}
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (this.dispatchOptionsRequest || CorsUtils.isPreFlightRequest(request)) {
this.processRequest(request, response);
if (response.containsHeader("Allow")) {
return;
}
}
super.doOptions(request, new HttpServletResponseWrapper(response) {
public void setHeader(String name, String value) {
if ("Allow".equals(name)) {
value = (StringUtils.hasLength(value) ? value + ", " : "") + HttpMethod.PATCH.name();
}
super.setHeader(name, value);
}
});
}
- org.springframework.web.servlet.FrameworkServlet#processRequest
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//...
try {
this.doService(request, response);
} catch (IOException | ServletException var16) {
failureCause = var16;
throw var16;
} catch (Throwable var17) {
failureCause = var17;
throw new NestedServletException("Request processing failed", var17);
} finally {
this.resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
this.logResult(request, response, (Throwable)failureCause, asyncManager);
this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
}
}
- org.springframework.web.servlet.DispatcherServlet#doService
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
//...
try {
this.doDispatch(request, response);
} finally {
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
this.restoreAttributesAfterInclude(request, attributesSnapshot);
}
if (this.parseRequestPath) {
ServletRequestPathUtils.setParsedRequestPath(previousRequestPath, request);
}
}
}
- org.springframework.web.servlet.DispatcherServlet#doDispatch
- mappedHandler.applyPreHandle(processedRequest, response)
- mv = ha.handle(processedRequest, response, mappedHandler.getHandler())
- mappedHandler.applyPostHandle(processedRequest, response, mv)
- this.processDispatchResult()
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;
mappedHandler = this.getHandler(processedRequest);
//...
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
//...
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//...
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);
}
}
}
- org.springframework.web.servlet.DispatcherServlet#processDispatchResult
- this.render(mv, request, response)
- mappedHandler.triggerAfterCompletion(request, response, (Exception)null)
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
//...
if (mv != null && !mv.wasCleared()) {
this.render(mv, request, response);
//...
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("No view rendering, null ModelAndView returned.");
}
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}
SpringMVC的执行流程
- 用户向服务器发送请求,请求被SpringMVC前端控制器DispatcherServlet捕获。
- DispatcherServlet对请求URL进行解析,得到请求资源标识符URI,判断请求URI对应的映射。
如果该URI不存在,则判断是否启用了DefaultServlet。
如果没有启用DefaultServlet,则直接报404。
如果启用了DefaultServlet,且找到了该URI,则返回对应的静态资源。
如果启用了DefaultServlet,但仍找不到该URI,则报404。 - 如果URI存在,会根据该URI,调用HandlerMapping获得该Handler(或Controller)配置的所有相关对象,包括Handler对象及Handler对象对应的拦截器,最后以HandlerExecutionChain执行链对象的形式返回。
- DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。
- 如果成功获得HandlerAdapter,此时将开始执行拦截器的perHandler。
- 提取Request中的模型数据,填充Handler入参,开始执行Handler(或Controller)方法,处理请求。在填充Handler入参的过程中,根据配置,Spring会完成一些额外工作,如:
1)HttpMessageConveter:将请求消息(如json、xml等数据)转换成一个对象,将对象转换成指定的响应信息。
2)数据转换:对请求消息进行数据转换,如String换成Integer、Double等。
3)数据格式化:对请求消息进行格式化,如将字符串转换成格式化数字或格式化日期等。
4)数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或者Error中。 - Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象。
- 控制器方法执行完后,开始执行拦截器的postHandler方法。
- 根据控制器方法返回的ModelAndView选择一个合适的ViewResolver进行视图解析,根据Model和View来渲染视图。
- 渲染视图完毕后执行拦截器的afterCompletion方法。
- 将渲染结果返回给客户端。
SpringMVC是跟着杨博超老师学的,给这位老师点赞。