在Spring MVC中,首先进行的是IoC容器的初始化,包括Root和DispatchServlet对应的content。在IoC容器准备好以后,就开始进行MVC的初始化,包括关于HandleMapping、ViewResolver等的初始化。

     在Spring MVC中,MVC的初始化在DispatchServlet的initStrategies方法中进行的。

  1. protected void initStrategies(ApplicationContext context) {  
  2.     initMultipartResolver(context);  
  3.     initLocaleResolver(context);  
  4.     initThemeResolver(context);  
  5.                //初始化从http请求到controller映射  
  6.     initHandlerMappings(context);  
  7.     initHandlerAdapters(context);                  
  8.     initHandlerExceptionResolvers(context);  
  9.     initRequestToViewNameTranslator(context);  
  10.                //初始化视图解析器  
  11.     initViewResolvers(context);  
  12. }  

      MVC框架需要的主要功能是根据http请求的信息选择合适的controller,调用controller后,根据返回的结果选择合适视图进行渲染。所以在这里主要关注一下这两个方法:initHandlerMappings和initViewResolvers。initHandlerMappings方法初始化了寻找controller的规则,initViewResolvers初始化视图解析的方法。

      那么首先来看一下initHandlerMappings。在spring mvc中,关于寻找controller的规则是用HandleMapping表示的,首先看一下HandleMapping接口类图:

HandlerMapping类图

     在HandlerMapping接口中,定义了getHandler方法,根据http请求,取得对应的处理对象。这个处理请求的对象用HandlerExecutionChain类表示,在这个类中,包含两个主要属性,一个是真正处理请求的handler,另外一个是Interceptor的集合。

     介绍完HandlerMapping接口后,就来看一下Spring MVC中是如何初始化HandlerMapping信息的:

  1. private void initHandlerMappings(ApplicationContext context) {  
  2.                 //主要工作是给这个属性赋值  
  3.         this.handlerMappings = null;  
  4.   
  5.         if (this.detectAllHandlerMappings) {  
  6.             // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.  
  7.                         //取得IoC容器中所有HandlerMapping类型的Bean  
  8.             Map<String, HandlerMapping> matchingBeans =  
  9.                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.classtruefalse);  
  10.             if (!matchingBeans.isEmpty()) {  
  11.                 this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());  
  12.                 // We keep HandlerMappings in sorted order.  
  13.                                 //注意排序  
  14.                 OrderComparator.sort(this.handlerMappings);  
  15.             }  
  16.         }  
  17.         else {  
  18.             try {  
  19.                 HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);  
  20.                 this.handlerMappings = Collections.singletonList(hm);  
  21.             }  
  22.             catch (NoSuchBeanDefinitionException ex) {  
  23.                 // Ignore, we'll add a default HandlerMapping later.  
  24.             }  
  25.         }  
  26.   
  27.         // Ensure we have at least one HandlerMapping, by registering  
  28.         // a default HandlerMapping if no other mappings are found.  
  29.         if (this.handlerMappings == null) {  
  30.             this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);  
  31.             if (logger.isDebugEnabled()) {  
  32.                 logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");  
  33.             }  
  34.         }  
  35.     }  
  

       在上述方法中,做的主要工作是是从容器中获取所有HandlerMapping类型的bean,然后将这些bean按照一定的规则进行排序(order接口),最后为handlerMap赋值,这样关于HandlerMapping的信息就全纪录在handlerMap中了。当有http请求时,会遍历handlerMap集合,选择合适的HandlerMapping实现,调用getHandler方法取得HandlerExecutionChain对象,然后执行真正的业务处理。

       在调用完controller后,Spring MVC会进行根据执行结果进行视图解析,这个任务是由ViewResolver进行的,关于ViewResolver的工作原理,见这篇文章:http://blog.csdn.net/prince2270/archive/2010/09/17/5891085.aspx

       那下面就来看一下Spring MVC是如何初始化ViewResolver信息的:

  1. private void initViewResolvers(ApplicationContext context) {  
  2.                 //所有的ViewResolver信息保存在这个属性中  
  3.         this.viewResolvers = null;  
  4.   
  5.         if (this.detectAllViewResolvers) {  
  6.             // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.  
  7.             Map<String, ViewResolver> matchingBeans =  
  8.                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.classtruefalse);  
  9.             if (!matchingBeans.isEmpty()) {  
  10.                 this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());  
  11.                 // We keep ViewResolvers in sorted order.  
  12.                 OrderComparator.sort(this.viewResolvers);  
  13.             }  
  14.         }  
  15.         else {  
  16.             try {  
  17.                 ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);  
  18.                 this.viewResolvers = Collections.singletonList(vr);  
  19.             }  
  20.             catch (NoSuchBeanDefinitionException ex) {  
  21.                 // Ignore, we'll add a default ViewResolver later.  
  22.             }  
  23.         }  
  24.   
  25.         // Ensure we have at least one ViewResolver, by registering  
  26.         // a default ViewResolver if no other resolvers are found.  
  27.         if (this.viewResolvers == null) {  
  28.             this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);  
  29.             if (logger.isDebugEnabled()) {  
  30.                 logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");  
  31.             }  
  32.         }  
  33.     }  

        与HandlerMapping信息的初始化方法类似,取得IoC容器中所有的ViewResolver类型的bean,将其放入到viewResolvers中,并按照一定的规则进行排序。

        经过MVC的初始化,所有的信息已经准备就绪,时刻准备着处理http请求了

欢迎加我的qq技术群425783133

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐