HttpServletBean
httpServletBean中Environment使用的是StandardServletEnvironment
StandardServletEnvironment
其中propertySources属性封装了如下信息:
- servletContext 和 servletConfig 
- jndiProperty 
- 系统环境变量 
- 系统属性 - //frameworkServlet中初始化 @Override public void initPropertySources(ServletContext servletContext, ServletConfig servletConfig) { WebApplicationContextUtils.initServletPropertySources( this.getPropertySources(), servletContext, servletConfig);//servletContext 和 servletConfig } - //AbstractEnvironment 构造方法中调用,构造StandardServletEnvironment对象时就有了。 @Override protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME)); propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) { propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));//jndiProperty } super.customizePropertySources(propertySources); } - @Override protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));//系统属性 propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));//系统环境变量 } 
init()
@Override
public final void init() throws ServletException {
   if (logger.isDebugEnabled()) {
      logger.debug("Initializing servlet '" + getServletName() + "'");
   }
   // Set bean properties from init parameters.
   try {
      PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
      BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);//this就是之后的DispatcherServlet
      ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
      bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));//注册Editor,复合resource类的,就用ResourceEditor来编辑
      initBeanWrapper(bw);
      bw.setPropertyValues(pvs, true);//将ServletConfig设置到dispatcherServlet
   }
   catch (BeansException ex) {
      logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
      throw ex;
   }
   // Let subclasses do whatever initialization they like.
   initServletBean();//模版方法
   if (logger.isDebugEnabled()) {
      logger.debug("Servlet '" + getServletName() + "' configured successfully");
   }
}
HttpServletBean主要作用
- 定义Environment
- 设置ServletConfig
FrameworkServlet
implements ApplicationContextAware
从spring中获取WebApplicationContext
initServletBean()
@Override
protected final void initServletBean() throws ServletException {
...
   try {
      this.webApplicationContext = initWebApplicationContext();
      initFrameworkServlet();
   }
   catch (ServletException ex) {
      this.logger.error("Context initialization failed", ex);
      throw ex;
   }
...
}
protected WebApplicationContext initWebApplicationContext() {
  //获取spring的容器,从ServletContext#getAttribute(WebApplicationContext.class.getName() + ".ROOT")
   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
              //将spring容器设置为springmvc容器的父容器
               cwac.setParent(rootContext);
            }
            configureAndRefreshWebApplicationContext(cwac);
         }
      }
   }
  //this.webApplicationContext = null & wac = null 是什么情况?
   if (wac == null) {
      // No context instance was injected at construction time -> see if one
      // has been registered in the servlet context. If one exists, it is assumed
      // that the parent context (if any) has already been set and that the
      // user has performed any initialization such as setting the context id
     //通过配置servlet中的contextAttribute参数,从ServletContext中获取指定名字的webApplicationContext
      wac = findWebApplicationContext();
   }
   if (wac == null) {
      // No context instance is defined for this servlet -> create a local one
      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.
     // 留给dispatcherServlet
      onRefresh(wac);
   }
   if (this.publishContext) {
      // Publish the context as a servlet context attribute.
      // FrameworkServlet.class.getName() + ".CONTEXT." + getServletName();
      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;
}
作用:
- 初始化WebApplicationContext 从ServletContext中获取
- initFrameworkServlet模版方法
servlet的webApplicationContext
- 已经构造好了webApplicationContext,在servlet构造方法中传入现有的对象。(主要用于servlet3.0以后,ServletContext.addServlet) 
- webApplication已经在ServletContext中了。可以通过配置来从servletContext中根据contextAttribute获取现有webApplicationContext - spring - org.springframework.web.servlet.DispatcherServlet - contextAttribute - hehe - contextConfigLocation - classpath:spring-mvc.xml - 1 - true 
- 自己创建(正常情况) 
webApplicationContext 中的内容
- environment
- parent
- contextConfigLocation :web.xml中配置,默认WEB-INFO/[servletname]-Servlet.xml
- servletContext
- servletConfig
- namespace
- applicationListener : ContextRefreshedEvent监听器,收到event后调用onRefresh() 方法
- postProcessWebApplicationContext() 后置处理
重写doGet doPost.....
将doXXX方法全部交由processRequest() 方法。doOptions 和 doTrace 根据参数判断自己处理还是交给父类
processRequest
- 对LocaleContext和RequestAttributes设置和恢复
- doService()
- 处理完后发布publishRequestHandledEvent
ServletRequestAttributes封装了request,可以从request和session中取值。
requestAttributes.requestCompleted();执行后,不能再对requestAttributes进行操作。
LocaleContextHolder/RequestContextHolder
//根据request设置LocaleContextHolder/RequestContextHolder,可提供locale和request,在service层。
initContextHolders(request, localeContext, requestAttributes);
localeContextHolder、inheritableLocaleContextHolder可以被子线程继承???
没搞懂localeContextHolder inheritableLocaleContextHolder两个ThreadLocal变量的作用,希望大神帮忙解答。
resetContextHolders(request, previousLocaleContext, previousAttributes); //为什么要恢复?怕影响Servlet外面的filter工作,可能有什么修改需要恢复?
publishRequestHandledEvent
配置:web.xml中配置springmvc servlet时配置,默认true。
用法:可以用来记录日志。

DispatcherServlet
初始化各种组件init()
- MutipartResolver
- LocaleResolver
- ThemeResolver
- HandlerMappings
- HandlerAdapters
- HandlerExceptionResolvers
- RequestToViewNameTranslator
- ViewResolvers
- FlashMapManager
doService()
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   if (logger.isDebugEnabled()) {
      String requestUri = urlPathHelper.getRequestUri(request);
      String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
      logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
            " processing " + request.getMethod() + " request for [" + requestUri + "]");
   }
   // Keep a snapshot of the request attributes in case of an include,
   // to be able to restore the original attributes after the include.
  //判断是否是include请求,如果是则对request做快照备份,结束后还原
   Map<String, Object> attributesSnapshot = null;
   if (WebUtils.isIncludeRequest(request)) {
      logger.debug("Taking snapshot of request attributes before include");
      attributesSnapshot = new HashMap<String, Object>();
      Enumeration<?> attrNames = request.getAttributeNames();
      while (attrNames.hasMoreElements()) {
         String attrName = (String) attrNames.nextElement();
         if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
            attributesSnapshot.put(attrName, request.getAttribute(attrName));
         }
      }
   }
   // Make framework objects available to handlers and view objects.
  //设置属性
   request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
   request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
   request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
   request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());
  //后面3个和flashMap有关。用于redirect传递参数。
   FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
   if (inputFlashMap != null) {
     //先取出flashmap放入INPUT_FLASH_MAP_ATTRIBUTE,再放入model中。在Controller中可以使用。
     //RedirectAttributes.addFlashAttribute() 将参数添加到session中
     //RedirectAttributes.addAttribute() 将参数拼接到url后。
      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 {
      doDispatch(request, response);
   }
   finally {
      if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
         return;
      }
      // Restore the original attribute snapshot, in case of an include.
      if (attributesSnapshot != null) {
         restoreAttributesAfterInclude(request, attributesSnapshot);
      }
   }
}
- 设置request一些属性
- 处理include请求快照
- doDispatch()
doDispatch()
- 根据request找handler 
- 根据handler找HandlerAdapter 
- 用Adapter处理handler 
- processDispathResult() 处理结果,包括找到view并渲染。 - 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 { //判断是否是Multipart 请求,用到MultipartResolver processedRequest = checkMultipart(request); multipartRequestParsed = processedRequest != request; // Determine handler for the current request. //根据request获取handler,用到handlerMapping mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; } // Determine handler adapter for the current request. //获取adatper HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler. String method = request.getMethod(); boolean isGet = "GET".equals(method); if (isGet || "HEAD".equals(method)) { long lastModified = ha.getLastModified(request, mappedHandler.getHandler()); if (logger.isDebugEnabled()) { String requestUri = urlPathHelper.getRequestUri(request); logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified); } if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) { return; } } 
 //interceptor#perHandler if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; } try { // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); } finally { //异步处理,则直接返回 if (asyncManager.isConcurrentHandlingStarted()) { return; } } applyDefaultViewName(request, mv); //interceptor#postHandler mappedHandler.applyPostHandle(processedRequest, response, mv); } catch (Exception ex) { dispatchException = ex; } processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); } catch (Exception ex) { triggerAfterCompletion(processedRequest, response, mappedHandler, ex); } catch (Error err) { triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); return; } // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } }
processDispatchResult()
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
      HandlerExecutionChain mappedHandler, ModelAndView mv, 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);
        //用到HanlderExceptionResolver
         mv = processHandlerException(request, response, handler, exception);
         errorView = (mv != null);
      }
   }
   // Did the handler return a view to render?
   if (mv != null && !mv.wasCleared()) {
     //渲染页面,用到themeResolver
      render(mv, request, response);
      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) {
     //触发Interceptor#afterCompletion()
      mappedHandler.triggerAfterCompletion(request, response, null);
   }
}

 
  
  
  
 
 
  
 
 
 