SpringMVC学习笔记

SpringMVC学习笔记

1. 执行流程

在这里插入图片描述

2. dispatcherServlet初始化过程

  • 执行静态代码块。加载配置文件DispatcherServlet.properties ,初始化属性defaultStrategies。用于后续init方法中的默认策略。
static {
		// Load default strategy implementations from properties file.
		// This is currently strictly internal and not meant to be customized
		// by application developers.
		try {
			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Could not load '" + DEFAULT_STRATEGIES_PATH + "': " + ex.getMessage());
		}
	}
  • 无参构造或者传入上下文的有参构造都会调用父类的set方法将dispatchOptionsRequest的值设为true(父类默认false)。该参数用于决定该servlet是否分发HTTP OPTIONS请求到doService方法。
  • onRefresh()方法。调用initStrategies方法初始化策略。
/**
	 * This implementation calls {@link #initStrategies}.
	 */
	@Override
	protected void onRefresh(ApplicationContext context) {
		initStrategies(context);
	}

	/**
	 * Initialize the strategy objects that this servlet uses.
	 * <p>May be overridden in subclasses in order to initialize further strategy objects.
	 */
	protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);
		initLocaleResolver(context);
		initThemeResolver(context);
		initHandlerMappings(context);
		initHandlerAdapters(context);
		initHandlerExceptionResolvers(context);
		initRequestToViewNameTranslator(context);
		initViewResolvers(context);
		initFlashMapManager(context);
	}
  • MultipartResolver: 文件上传。先从上下文中获取bean,如果没有则不提供该解析器。
/**
	 * Initialize the MultipartResolver used by this class.
	 * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
	 * no multipart handling is provided.
	 */
	private void initMultipartResolver(ApplicationContext context) {
		try {
			this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Default is no multipart resolver.
			this.multipartResolver = null;
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
						"': no multipart request handling provided");
			}
		}
	}
    public interface MultipartResolver {
        // 判断请求是否包含文件流
        boolean isMultipart(HttpServletRequest request);
        // 将请求解析成MultipartHttpServletRequest
        MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException;
        void cleanupMultipart(MultipartHttpServletRequest request);
    }
  • LocaleResolver: 国际化。先从上下文获取,没有则从默认策略中取。
  • ThemeResolver: 主题。先从上下文获取,没有则从默认策略中取。
  • HandlerMappings: 处理器映射器。
private void initHandlerMappings(ApplicationContext context) {
   this.handlerMappings = null;
    // 扫描所有的handlerMapping
   if (this.detectAllHandlerMappings) {
      // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
      // 找到当前容器所有的处理器映射器,包括父级容器的
      Map<String, HandlerMapping> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
      if (!matchingBeans.isEmpty()) {
         this.handlerMappings = new ArrayList<>(matchingBeans.values());
         // We keep HandlerMappings in sorted order.
         AnnotationAwareOrderComparator.sort(this.handlerMappings);
      }
   }
   // 只扫描beanName为“handlerMapping”的处理器映射器
   else {
      try {
         HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
         // 将其设为单例
         this.handlerMappings = Collections.singletonList(hm);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default HandlerMapping later.
      }
   }

   // Ensure we have at least one HandlerMapping, by registering
   // a default HandlerMapping if no other mappings are found.
   // 如果以上扫描之后没有找到handlerMapping,则从默认策略中获取
   if (this.handlerMappings == null) {
      this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
      if (logger.isDebugEnabled()) {
         logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
      }
   }
}
  • HandlerAdapters: 处理器适配器。
private void initHandlerAdapters(ApplicationContext context) {
   this.handlerAdapters = null;
    // 扫描所有的处理器适配器
   if (this.detectAllHandlerAdapters) {
      // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
      // 找当前容器中以及父级容器中所有的处理器适配器
       Map<String, HandlerAdapter> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
      if (!matchingBeans.isEmpty()) {
         this.handlerAdapters = new ArrayList<>(matchingBeans.values());
         // We keep HandlerAdapters in sorted order.
         AnnotationAwareOrderComparator.sort(this.handlerAdapters);
      }
   }
   // 只扫描beanName为“handlerAdapter”的处理器适配器
   else {
      try {
         HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
         // 设置为单例
         this.handlerAdapters = Collections.singletonList(ha);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default HandlerAdapter later.
      }
   }

   // Ensure we have at least some HandlerAdapters, by registering
   // default HandlerAdapters if no other adapters are found.
   // 如果以上代码没有获取到处理器映射器,则从默认策略中获取。
   if (this.handlerAdapters == null) {
      this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
      if (logger.isDebugEnabled()) {
         logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
      }
   }
}
  • HandlerExceptionResovlers: 处理器异常。和处理器映射器、处理器适配器的初始化方法类似。
  • RequestToViewNameTranslator: 请求视图转换器
  • ViewResolvers:视图解析器。
public interface ViewResolver {

	@Nullable
	View resolveViewName(String viewName, Locale locale) throws Exception;

}
private void initViewResolvers(ApplicationContext context) {
   this.viewResolvers = null;
   // 根据属性判断是否扫描全部视图解析器
   if (this.detectAllViewResolvers) {
      // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
      // 扫描当前容器以及父容器中所有的视图解析器
      Map<String, ViewResolver> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
      if (!matchingBeans.isEmpty()) {
         this.viewResolvers = new ArrayList<>(matchingBeans.values());
         // We keep ViewResolvers in sorted order.
         AnnotationAwareOrderComparator.sort(this.viewResolvers);
      }
   }
   // 只扫描beanName为“viewResolver”的bean
   else {
      try {
         ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
         // 单例
         this.viewResolvers = Collections.singletonList(vr);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default ViewResolver later.
      }
   }

   // Ensure we have at least one ViewResolver, by registering
   // a default ViewResolver if no other resolvers are found.
   // 没有获取到识图解析器,则从默认策略中获取
   if (this.viewResolvers == null) {
      this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
      if (logger.isDebugEnabled()) {
         logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
      }
   }
}
  • FlashMapManager: flashMap检索和保存。重定向属性存储(maybe)。

3. 关键方法

  • getDefaultStrategy(ApplicationContext context, Class strategyInterface),该方法用于initStrategies()中初始化各个属性。
protected <T> T getDefaultStrategy(ApplicationContext context, Class<T> strategyInterface) {
   List<T> strategies = getDefaultStrategies(context, strategyInterface);
                        ------------------------------------------------
   if (strategies.size() != 1) {
      throw new BeanInitializationException(
            "DispatcherServlet needs exactly 1 strategy for interface [" + strategyInterface.getName() + "]");
   }
   return strategies.get(0);
}
protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {
   String key = strategyInterface.getName();
   String value = defaultStrategies.getProperty(key);
   // 默认策略配置中有则遍历生产类,没有则返回空
   if (value != null) {
      String[] classNames = StringUtils.commaDelimitedListToStringArray(value);
      List<T> strategies = new ArrayList<>(classNames.length);
      for (String className : classNames) {
         try {
             // 反射生成策略类,此处使用getAutowireCapableBeanFactory创建bean
            Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());
            Object strategy = createDefaultStrategy(context, clazz);
            strategies.add((T) strategy);
         }
         catch (ClassNotFoundException ex) {
            throw new BeanInitializationException(
                  "Could not find DispatcherServlet's default strategy class [" + className +
                  "] for interface [" + key + "]", ex);
         }
         catch (LinkageError err) {
            throw new BeanInitializationException(
                  "Unresolvable class definition for DispatcherServlet's default strategy class [" +
                  className + "] for interface [" + key + "]", err);
         }
      }
      return strategies;
   }
   else {
       // 返回空
      return new LinkedList<>();
   }
}
  • doService(HttpServletRequest request, HttpServletResponse response)
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   // 打印日志
   if (logger.isDebugEnabled()) {
      String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";
      logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +
            " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
   }

   // Keep a snapshot of the request attributes in case of an include,
   // to be able to restore the original attributes after the include.
   // 保存一份副本,用于doInclude类型请求(maybe)
   Map<String, Object> attributesSnapshot = null;
   if (WebUtils.isIncludeRequest(request)) {
      attributesSnapshot = new HashMap<>();
      Enumeration<?> attrNames = request.getAttributeNames();
      while (attrNames.hasMoreElements()) {
         String attrName = (String) attrNames.nextElement();
         if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
            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());

   if (this.flashMapManager != null) {// ???
      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);
   }

    // 关键方法 “the actual dispatching”
   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);
         }
      }
   }
}
  • doDispatch(HttpServletRequest request, HttpServletResponse response)
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 {
         processedRequest = checkMultipart(request);// 如果request不为空并且isMultipart,则将request解析成为MultipartHttpServletRequest
         multipartRequestParsed = (processedRequest != request);// 是否是文件流请求

         // Determine handler for the current request.
         // 遍历处理器映射器list,获取与当前requset匹配的第一个处理器执行链
         mappedHandler = getHandler(processedRequest);
         if (mappedHandler == null) {
             // 404
            noHandlerFound(processedRequest, response);
            return;
         }

         // Determine handler adapter for the current request.
         // 通过处理器执行链获取处理器映射器。遍历处理器映射器list,返回第一个supports(handler)为true的处理器适配器
         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)) {
             // 处理lastModified(????)
            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;
            }
         }
         // 处理器执行链调用拦截器的preHandle方法
         if (!mappedHandler.applyPreHandle(processedRequest, response)) {
            return;
         }

         // Actually invoke the handler.
         // 处理器适配器调用controller
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
         // 如果是异步请求则return
         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }
        
         // 给空mv设置默认name
         applyDefaultViewName(processedRequest, mv);
         
         // 处理器执行链调用拦截器的postHandle方法         
         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);
      }
      // 将异常设置到mv中,调用拦截器的afterCompletion方法
      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);
         }
      }
   }
}

4. doService

  1. 打印日志
  2. 保存request副本用于include
  3. 给request设置属性(localeResolver、themeResolver、flashMapManager)
  4. 调用doDispatcher
  5. 处理异常、释放资源

5. doDispatcher

  1. 判断是否为文件流请求并解析(multipartResolver)
  2. 遍历handlerMappings,根据request用getHandle()找到handler(handlerMappings)
  3. 遍历handlerAdapters,根据handler用supports()找到adapter(handlerAdapters)
  4. 处理last-modify
  5. 调用拦截器的preHandle方法
  6. 处理器执行(调用controller)
  7. 判断是否为异步,异步则return
  8. 给没有值的mv设置默认name(requestToViewNameTranslator)
  9. 调用拦截器的postHandle方法
  10. 捕获dispatcherException
  11. 处理dispatcher异常、解析modelAndView;调用拦截器的afterCompletion方法(viewResolver、dispatcherExceptionHandler)
  12. 处理异常、释放资源

6. SpringMVC容器和Spring容器关系(not sure)

两者都是容器,都能管理对象。springMVC管理controller对象,spring容器管理service、dao对象。SpringMVC容器和Spring容器是父子容器的概念,Spring容器为父容器,SpringMVC容器为子容器,子容器可以访问父容器中管理的对象,但是父容器不能访问子容器中的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值