Web容器初始化过程

阅读目录 一、SpringMVC启动过程 二、ServletContext、ApplicationContext和WebApplicationContext区别? 三、总结 四、参考资料 回到顶部 一、SpringMVC启动过程 Spring的MVC是基于Servlet功能实现的,每个web工程中都有一个web.xml文件,web容器在启动的时候会加载这个配置文件,当一个web应用加载到web容器中后,在web应用开始响应客户端的请求之前,要按照顺序执行下面几个步骤: 1、实例化部署描述符中的元素标识的时间监听器的实例; 复制代码 org.springframework.web.context.ContextLoaderListener 复制代码 2、在实现了ServletContextListener接口的监听器实例中,调用contextInitialized()方法。ContextLoaderListener实现了ServletContextListener接口,ServletContextListener作为Servlet的监听者,会在ServletContext创建、销毁过程中监听ServletContextEvent事件,然后进行响应的处理。换句话说,就是在启动web容器时,ContextLoaderListener类会自动装配ApplicationContext的配置信息。 复制代码 public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); }   // 这里调用其父类ContextLoader的initWebApplicationContext进行初始化工作    public void contextInitialized(ServletContextEvent event) { this.initWebApplicationContext(event.getServletContext()); }    public void contextDestroyed(ServletContextEvent event) { this.closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); } } 复制代码   ContextLoaderListener类继承了ContextLoader,后者是实际的ServletContextListener接口实现者,这里用到了代理模式,利用ContextLoader类创建Spring application context,并将其注册到ServletContext中去。ContextLoaderListener就是调用ContextLoader类的initWebApplicationContext()方法和closeWebApplicationContext()方法来实现ServletContext的创建和销毁工作的。      其中,initWebApplicationContext()方法主要完成了两个部分的工作:一是查看是否已经指定父容器,如果不存在则设置其父容器。二是将Spring WebApplicationContext放置到线程Map中。 复制代码 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!"); } else { Log logger = LogFactory.getLog(ContextLoader.class); servletContext.log("Initializing Spring root WebApplicationContext"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { if (this.context == null) { this.context = this.createWebApplicationContext(servletContext); } if (this.context instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context; if (!cwac.isActive()) {               //查看是否指定父容器 if (cwac.getParent() == null) { ApplicationContext parent = this.loadParentContext(servletContext); cwac.setParent(parent); } this.configureAndRefreshWebApplicationContext(cwac, servletContext); } } servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); //将WebApplicationContext放置到线程Map中 if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } return this.context; } catch (RuntimeException var8) { logger.error("Context initialization failed", var8); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8); throw var8; } catch (Error var9) { logger.error("Context initialization failed", var9); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9); throw var9; } } } 复制代码 在初始化方法执行后,将WebApplicationContext存到了两个地方,分别是ServletContext和currentContextPerThread中,我们可以通过这两个地方来获取WebApplicationContext:1.从servletContext中去拿;2.从当前的线程Map中去拿。 3、实例化部署符中元素标识的过滤器实例,并调用每个过滤器实例的init()方法。 4、实例化部署符中元素标识的Servlet实例,按照该元素包含的load-on-startup顺序,调用每个Servlet实例的init()方法。   org.springframework.web.servlet.DispatcherServlet 在SpringMVC的架构中,DispatcherServlet主要负责客户端请求的分发,起到控制器的作用。DispatcherServlet是实现Servlet接口的实现类,其结构如下图所示。Servlet的生命周期由Servlet的容器来控制,主要分为初始化、运行和销毁三个阶段,分别对应三个方法:init()、service()和destory()。   在DispatcherServlet的父类HTTPServletBean中,重写了init()方法,主要实现将当前的Servlet类实例转换为BeanWrapper类型实例,以便使用Spring中提供的注入功能进行相应属性的注入。   在DispatcherServlet的父类FameworkServelet中,重写了service()方法,对于不同的方法,Spring统一将程序引导至processRequest(request,response)中,processRequest方法再对处理请求进行了一些准备工作后,又将细节实现转移到了doService方法中。 复制代码   protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method = request.getMethod(); if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) { this.processRequest(request, response); } else { super.service(request, response); } } protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext(); LocaleContext localeContext = this.buildLocaleContext(request); RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes); WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor()); this.initContextHolders(request, localeContext, requestAttributes); try { //调用DispatcherServlet的doService()方法 this.doService(request, response); } catch (ServletException var17) { failureCause = var17; throw var17; } catch (IOException var18) { failureCause = var18; throw var18; } catch (Throwable var19) { failureCause = var19; throw new NestedServletException("Request processing failed", var19); } finally { this.resetContextHolders(request, previousLocaleContext, previousAttributes); if (requestAttributes != null) { requestAttributes.requestCompleted(); } if (this.logger.isDebugEnabled()) { if (failureCause != null) { this.logger.debug("Could not complete request", (Throwable)failureCause); } else if (asyncManager.isConcurrentHandlingStarted()) { this.logger.debug("Leaving response open for concurrent processing"); } else { this.logger.debug("Successfully completed request"); } } this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause); } } 复制代码 复制代码 protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { if (this.logger.isDebugEnabled()) { String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : ""; this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]"); } Map attributesSnapshot = null; if (WebUtils.isIncludeRequest(request)) { attributesSnapshot = new HashMap(); Enumeration attrNames = request.getAttributeNames(); label108: while(true) { String attrName; do { if (!attrNames.hasMoreElements()) { break label108; } attrName = (String)attrNames.nextElement(); } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet")); attributesSnapshot.put(attrName, request.getAttribute(attrName)); } } request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext()); request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver); request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver); request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource()); FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response); if (inputFlashMap != null) { request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap)); } request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap()); request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager); try { // 最终的请求处理函数 this.doDispatch(request, response); } finally { if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) { this.restoreAttributesAfterInclude(request, attributesSnapshot); } } } 复制代码   经过层层的准备工作,最终在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 { try { ModelAndView mv = null; Exception dispatchException = null; try { processedRequest = this.checkMultipart(request); multipartRequestParsed = processedRequest != request; //根据request信息寻找对应的处理器 mappedHandler = this.getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { this.noHandlerFound(processedRequest, response); return; } //根据处理器寻找对应的处理器适配器 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; } //返回视图 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) { return; } this.applyDefaultViewName(request, mv); mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception var19) { dispatchException = var19; } this.processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception var20) { this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20); } catch (Error var21) { this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21); } } finally { if (asyncManager.isConcurrentHandlingStarted()) { if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, res
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信