初始化阶段 ---> 运行(调用)阶段
源码分析
一、初始化阶段
1. 根据配置得知,在DispatcherServlet里没找到init方法,然后在它的父类HttpServletBean找到了init方法的入口,进入HttpServletBean的init()方法
public final void init() throws ServletException { //去掉了if判断 // Set bean properties from init parameters. PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties); if (!pvs.isEmpty()) { try { //定位资源 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) { if (logger.isErrorEnabled()) { logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex); } throw ex; } } // Let subclasses do whatever initialization they like. initServletBean();//Ctrl+Alt+B 选择 FrameworkServlet //去掉了if判断 }
2.在initServletBean()上,按住Ctrl+Alt+B,选择FrameworkServlet进入FrameworkServlet的initServletBean方法
@Override protected final void initServletBean() throws ServletException { getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'"); //去掉了if判断 long startTime = System.currentTimeMillis(); try { this.webApplicationContext = initWebApplicationContext();//Ctrl + 鼠标左键 initFrameworkServlet(); } //去掉了catch块,和下面的if判断 }
3. 在 initWebApplicationContext() 方法上,按住 Ctrl+鼠标左键进入initWebApplicationContext方法
protected WebApplicationContext initWebApplicationContext() { WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); WebApplicationContext wac = null; if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac);//支线(会进入SpringIOC的定位阶段) } } } if (wac == null) { //在构建时没有注入上下文实例——>查看是否有一个已经在servlet上下文中注册。 //如果存在,则假定已经设置了父上下文(如果有), //并且用户已经执行了任何初始化,例如设置上下文id wac = findWebApplicationContext(); } if (wac == null) { //没有为这个servlet定义上下文实例——>创建一个本地实例 wac = createWebApplicationContext(rootContext); } if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. onRefresh(wac); //Ctrl+Alt+B 选择 DispatcherServlet } if (this.publishContext) { // Publish the context as a servlet context attribute. String attrName = getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); if (this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]"); } } return wac; }
4. 若走configureAndRefreshWebApplicationContext方法,会进入Spring IOC 定位阶段,这里不展开,在onRefresh方法上,按住Ctrl+Alt+B 选择进入DispatcherServlet的onRefresh方法
@Override protected void onRefresh(ApplicationContext context) { initStrategies(context);//Ctrl+鼠标左键 }
5. 在initStrategies方法上,按住Ctrl+鼠标左键,进入自身的initStrategies方法,初始化九大策略
protected void initStrategies(ApplicationContext context) { //多文件上传的组件 initMultipartResolver(context); //初始化本地语言环境 initLocaleResolver(context); //初始化模板处理器 initThemeResolver(context); //handlerMapping initHandlerMappings(context); //初始化参数适配器 initHandlerAdapters(context); //初始化异常拦截器 initHandlerExceptionResolvers(context); //初始化视图预处理器 initRequestToViewNameTranslator(context); //初始化视图转换器 initViewResolvers(context); //初始化Flash管理器 initFlashMapManager(context); }
二、运行(调用)阶段
运行(调用)阶段,核心方法是DispatcherServlet的doServlet(),核心逻辑由doDispatch()实现 6. 初始化完成后,进入运行(调用)阶段,进入DispatcherServlet的doServlet()
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { //去掉了if判断以及request赋值 try { doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Restore the original attribute snapshot, in case of an include. if (attributesSnapshot != null) { restoreAttributesAfterInclude(request, attributesSnapshot); } } } }
7. 在doDispatch() 方法上,按住Ctrl+鼠标左键进入自身的doDispatch方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { ModelAndView mv = null; Exception dispatchException = null; try { // 1.检查是否是文件上传的请求 processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. // 2.取得处理当前请求的controller,这里也称为hanlder,处理器, // 第一个步骤的意义就在这里体现了.这里并不是直接返回controller, // 而是返回的HandlerExecutionChain请求处理器链对象, // 该对象封装了handler和interceptors. mappedHandler = getHandler(processedRequest); // 如果handler为空,则返回404 if (mappedHandler == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //3. 获取处理request的处理器适配器handler adapter HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. // 处理 last-modified 请求头 String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { 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; } // Actually invoke the handler. // 4.实际的处理器处理请求,返回结果视图对象 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } // 结果视图对象的处理 applyDefaultViewName(processedRequest, mv); mappedHandler.applyPostHandle(processedRequest, response, mv);//支线 } catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);//主线 } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { // 请求成功响应之后的方法 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }
8. 在getHandler方法上,按住Ctrl+鼠标左键进入getHandler方法后,返回的是HandlerExecutionChain
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } } return null; }
9. Ctrl+Alt+键盘左键头返回到第7步,在applyPreHandle方法上,按住Ctrl+Alt+B进入HandlerExecutionChain的applyPreHandle方法
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i]; if (!interceptor.preHandle(request, response, this.handler)) { triggerAfterCompletion(request, response, null); return false; } this.interceptorIndex = i; } } return true; }
10. 在preHandle方法上,按Ctrl+Alt+B进入HandlerInterceptor的preHandle方法,默认返回true。 preHandle是handle的前置处理
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; }
11. 按住Ctrl+Alt+键盘左键头返回到第7步,在handle方法上,按住Ctrl+Alt+B,进入AbstractHandlerMethodAdapter的handle方法
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); }
12. 在handleInternal方法上,按住Ctrl+Alt+B进入RequestMappingHandlerAdapter的handleInternal方法
protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; checkRequest(request); // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { HttpSession session = request.getSession(false); if (session != null) { Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
13. 在invokeHandlerMethod方法上,按住Ctrl+鼠标左键进入自身的invokeHandlerMethod方法
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { //去掉了if判断和finally return getModelAndView(mavContainer, modelFactory, webRequest); }
14. 在getModelAndView方法上,按住Ctrl+鼠标左键进入自身的getModelAndView方法,返回ModelAndView
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); if (mavContainer.isRequestHandled()) { return null; } ModelMap model = mavContainer.getModel(); ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; }
15. 按住Ctrl+Alt+键盘左键头返回到第7步,在applyPostHandle方法上,按住Ctrl+鼠标左键,进入HandlerExecutionChain的applyPostHandle方法
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception { HandlerInterceptor[] interceptors = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) { for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } }
16. 在postHandle方法上,按住Ctrl+Alt+B,选择HandlerInterceptor,进入到HandlerInterceptor的postHandle方法,postHandle方法为handle的后置方法
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { }
17. 按住Ctrl+Alt+键盘左键头返回到第7步,在processDispatchResult方法上,按住Ctrl+鼠标左键进入processDispatchResult方法
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception { boolean errorView = false; if (exception != null) { if (exception instanceof ModelAndViewDefiningException) { logger.debug("ModelAndViewDefiningException encountered", exception); mv = ((ModelAndViewDefiningException) exception).getModelAndView(); } else { Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); mv = processHandlerException(request, response, handler, exception); errorView = (mv != null); } } // Did the handler return a view to render? if (mv != null && !mv.wasCleared()) { render(mv, request, response);//Ctrl+鼠标左键 if (errorView) { WebUtils.clearErrorRequestAttributes(request); } } else { if (logger.isDebugEnabled()) { logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() + "': assuming HandlerAdapter completed request handling"); } } if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) { // Concurrent handling started during a forward return; } if (mappedHandler != null) { mappedHandler.triggerAfterCompletion(request, response, null); } }
18. 在render方法上,按住Ctrl+鼠标左键进入自身的render方法
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { // Determine locale for request and apply it to the response. Locale locale = (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); response.setLocale(locale); View view; String viewName = mv.getViewName(); if (viewName != null) { // We need to resolve the view name. view = resolveViewName(viewName, mv.getModelInternal(), locale, request); if (view == null) { throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + getServletName() + "'"); } } else { // No need to lookup: the ModelAndView object contains the actual View object. view = mv.getView(); if (view == null) { throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " + "View object in servlet with name '" + getServletName() + "'"); } } // Delegate to the View object for rendering. if (logger.isDebugEnabled()) { logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'"); } try { if (mv.getStatus() != null) { response.setStatus(mv.getStatus().value()); } view.render(mv.getModelInternal(), request, response);// } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'", ex); } throw ex; } }
19. 在render方法上,按住Ctrl+Alt+B,选择的AbstractView,进入AbstractView的render方法,完成运行(调用)阶段。
public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { if (logger.isTraceEnabled()) { logger.trace("Rendering view with name '" + this.beanName + "' with model " + model + " and static attributes " + this.staticAttributes); } Map<String, Object> mergedModel = createMergedOutputModel(model, request, response); prepareResponse(request, response); renderMergedOutputModel(mergedModel, getRequestToExpose(request), response); }