DispatcherServlet

来源:互联网 发布:淘宝上买不到的东西 编辑:程序博客网 时间:2024/06/17 05:25

DispatcherServlet初始化顺序

继承体系结构如下所示:

 

1、HttpServletBean继承HttpServlet,因此在Web容器启动时将调用它的init方法,该初始化方法的主要作用

:::将Servlet初始化参数(init-param)设置到该组件上(如contextAttribute、contextClass、namespace、contextConfigLocation),通过BeanWrapper简化设值过程,方便后续使用;

:::提供给子类初始化扩展点,initServletBean(),该方法由FrameworkServlet覆盖。

 

Java代码  收藏代码
  1. public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware{  
  2. @Override  
  3.     public final void init() throws ServletException {  
  4.        //省略部分代码  
  5.        //1、如下代码的作用是将Servlet初始化参数设置到该组件上  
  6. //如contextAttribute、contextClass、namespace、contextConfigLocation;  
  7.        try {  
  8.            PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);  
  9.            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);  
  10.            ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());  
  11.            bw.registerCustomEditor(Resource.classnew ResourceEditor(resourceLoader, this.environment));  
  12.            initBeanWrapper(bw);  
  13.            bw.setPropertyValues(pvs, true);  
  14.        }  
  15.        catch (BeansException ex) {  
  16.            //…………省略其他代码  
  17.        }  
  18.        //2、提供给子类初始化的扩展点,该方法由FrameworkServlet覆盖  
  19.        initServletBean();  
  20.        if (logger.isDebugEnabled()) {  
  21.            logger.debug("Servlet '" + getServletName() + "' configured successfully");  
  22.        }  
  23.     }  
  24.     //…………省略其他代码  
  25. }  

   

2、FrameworkServlet继承HttpServletBean,通过initServletBean()进行Web上下文初始化,该方法主要覆盖一下两件事情:

    初始化web上下文;

    提供给子类初始化扩展点;

Java代码  收藏代码
  1. public abstract class FrameworkServlet extends HttpServletBean {  
  2. @Override  
  3.     protected final void initServletBean() throws ServletException {  
  4.         //省略部分代码  
  5.        try {  
  6.              //1、初始化Web上下文  
  7.            this.webApplicationContext = initWebApplicationContext();  
  8.              //2、提供给子类初始化的扩展点  
  9.            initFrameworkServlet();  
  10.        }  
  11.         //省略部分代码  
  12.     }  
  13. }  

 

Java代码  收藏代码
  1. protected WebApplicationContext initWebApplicationContext() {  
  2.         //ROOT上下文(ContextLoaderListener加载的)  
  3.        WebApplicationContext rootContext =  
  4.               WebApplicationContextUtils.getWebApplicationContext(getServletContext());  
  5.        WebApplicationContext wac = null;  
  6.        if (this.webApplicationContext != null) {  
  7.            // 1、在创建该Servlet注入的上下文  
  8.            wac = this.webApplicationContext;  
  9.            if (wac instanceof ConfigurableWebApplicationContext) {  
  10.               ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;  
  11.               if (!cwac.isActive()) {  
  12.                   if (cwac.getParent() == null) {  
  13.                       cwac.setParent(rootContext);  
  14.                   }  
  15.                   configureAndRefreshWebApplicationContext(cwac);  
  16.               }  
  17.            }  
  18.        }  
  19.        if (wac == null) {  
  20.              //2、查找已经绑定的上下文  
  21.            wac = findWebApplicationContext();  
  22.        }  
  23.        if (wac == null) {  
  24.             //3、如果没有找到相应的上下文,并指定父亲为ContextLoaderListener  
  25.            wac = createWebApplicationContext(rootContext);  
  26.        }  
  27.        if (!this.refreshEventReceived) {  
  28.              //4、刷新上下文(执行一些初始化)  
  29.            onRefresh(wac);  
  30.        }  
  31.        if (this.publishContext) {  
  32.            // Publish the context as a servlet context attribute.  
  33.            String attrName = getServletContextAttributeName();  
  34.            getServletContext().setAttribute(attrName, wac);  
  35.            //省略部分代码  
  36.        }  
  37.        return wac;  
  38.     }  

  

从initWebApplicationContext()方法可以看出,基本上如果ContextLoaderListener加载了上下文将作为根上下文(DispatcherServlet的父容器)。 

最后调用了onRefresh()方法执行容器的一些初始化,这个方法由子类实现,来进行扩展。

  

3、DispatcherServlet继承FrameworkServlet,并实现了onRefresh()方法提供一些前端控制器相关的配置: 

Java代码  收藏代码
  1. public class DispatcherServlet extends FrameworkServlet {  
  2.      //实现子类的onRefresh()方法,该方法委托为initStrategies()方法。  
  3.     @Override  
  4.     protected void onRefresh(ApplicationContext context) {  
  5.        initStrategies(context);  
  6.     }  
  7.    
  8.     //初始化默认的Spring Web MVC框架使用的策略(如HandlerMapping)  
  9.     protected void initStrategies(ApplicationContext context) {  
  10.        initMultipartResolver(context);  
  11.        initLocaleResolver(context);  
  12.        initThemeResolver(context);  
  13.        initHandlerMappings(context);  
  14.        initHandlerAdapters(context);  
  15.        initHandlerExceptionResolvers(context);  
  16.        initRequestToViewNameTranslator(context);  
  17.        initViewResolvers(context);  
  18.        initFlashMapManager(context);  
  19.     }  
  20. }  

  

从如上代码可以看出,DispatcherServlet启动时会进行我们需要的Web层Bean的配置,如HandlerMapping、HandlerAdapter等,而且如果我们没有配置,还会给我们提供默认的配置。

 

从如上代码我们可以看出,整个DispatcherServlet初始化的过程和做了些什么事情,具体主要做了如下两件事情:

1、初始化Spring Web MVC使用的Web上下文,并且可能指定父容器为(ContextLoaderListener加载了根上下文);

2、初始化DispatcherServlet使用的策略,如HandlerMapping、HandlerAdapter等。 

 

服务器启动时的日志分析(此处加上了ContextLoaderListener从而启动ROOT上下文容器): 

 信息: Initializing Spring root WebApplicationContext //由ContextLoaderListener启动ROOT上下文

 

2012-03-12 13:33:55 [main] INFO  org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started

2012-03-12 13:33:55 [main] INFO  org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Mon Mar 12 13:33:55 CST 2012]; root of context hierarchy

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader - Loading bean definitions

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 0 bean definitions from location pattern [/WEB-INF/ContextLoaderListener.xml]

2012-03-12 13:33:55 [main] DEBUG org.springframework.web.context.support.XmlWebApplicationContext - Bean factory for Root WebApplicationContext: org.springframework.beans.factory.support.DefaultListableBeanFactory@1c05ffd: defining beans []; root of factory hierarchy

2012-03-12 13:33:55 [main] DEBUG org.springframework.web.context.support.XmlWebApplicationContext - Bean factory for Root WebApplicationContext:

2012-03-12 13:33:55 [main] DEBUG org.springframework.web.context.ContextLoader - Published root WebApplicationContext as ServletContext attribute with name [org.springframework.web.context.WebApplicationContext.ROOT] //将ROOT上下文绑定到ServletContext

2012-03-12 13:33:55 [main] INFO  org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 438 ms  //到此ROOT上下文启动完毕

 

 2012-03-12 13:33:55 [main] DEBUG org.springframework.web.servlet.DispatcherServlet - Initializing servlet 'chapter2'

信息: Initializing Spring FrameworkServlet 'chapter2'  //开始初始化FrameworkServlet对应的Web上下文

2012-03-12 13:33:55 [main] INFO  org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'chapter2': initialization started

2012-03-12 13:33:55 [main] DEBUG org.springframework.web.servlet.DispatcherServlet - Servlet with name 'chapter2' will try to create custom WebApplicationContext context of class 'org.springframework.web.context.support.XmlWebApplicationContext', using parent context [Root WebApplicationContext: startup date [Mon Mar 12 13:33:55 CST 2012]; root of context hierarchy]

//此处使用Root WebApplicationContext作为父容器。

2012-03-12 13:33:55 [main] INFO  org.springframework.web.context.support.XmlWebApplicationContext - Refreshing WebApplicationContext for namespace 'chapter2-servlet': startup date [Mon Mar 12 13:33:55 CST 2012]; parent: Root WebApplicationContext

2012-03-12 13:33:55 [main] INFO  org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/chapter2-servlet.xml]

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader - Loading bean definitions

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.BeanDefinitionParserDelegate - Neither XML 'id' nor 'name' specified - using generated bean name[org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping#0]  //我们配置的HandlerMapping

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.BeanDefinitionParserDelegate - Neither XML 'id' nor 'name' specified - using generated bean name[org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#0] //我们配置的HandlerAdapter

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.BeanDefinitionParserDelegate - Neither XML 'id' nor 'name' specified - using generated bean name [org.springframework.web.servlet.view.InternalResourceViewResolver#0] //我们配置的ViewResolver

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.BeanDefinitionParserDelegate - No XML 'id' specified - using '/hello' as bean name and [] as aliases 

//我们的处理器(HelloWorldController)

2012-03-12 13:33:55 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 4 bean definitions from location pattern [/WEB-INF/chapter2-servlet.xml]

2012-03-12 13:33:55 [main] DEBUG org.springframework.web.context.support.XmlWebApplicationContext - Bean factory for WebApplicationContext for namespace 'chapter2-servlet': org.springframework.beans.factory.support.DefaultListableBeanFactory@1372656: defining beans [org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping#0,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#0,org.springframework.web.servlet.view.InternalResourceViewResolver#0,/hello]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@1c05ffd

//到此容器注册的Bean初始化完毕

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.web.servlet.DispatcherServlet - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver'

//默认的LocaleResolver注册

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'org.springframework.web.servlet.theme.FixedThemeResolver'

//默认的ThemeResolver注册

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping#0'

//发现我们定义的HandlerMapping 不再使用默认的HandlerMapping。

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#0'

//发现我们定义的HandlerAdapter 不再使用默认的HandlerAdapter。

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver'

//异常处理解析器ExceptionResolver

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver'

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.web.servlet.view.InternalResourceViewResolver#0'

 

2012-03-12 13:33:56 [main] DEBUG org.springframework.web.servlet.DispatcherServlet - Published WebApplicationContext of servlet 'chapter2' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.chapter2]

//绑定FrameworkServlet初始化的Web上下文到ServletContext

2012-03-12 13:33:56 [main] INFO  org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'chapter2': initialization completed in  297 ms

2012-03-12 13:33:56 [main] DEBUG org.springframework.web.servlet.DispatcherServlet - Servlet 'chapter2' configured successfully

//到此完整流程结束 

  

从如上日志我们也可以看出,DispatcherServlet会进行一些默认的配置。接下来我们看一下默认配置吧。

  

3.5、DispatcherServlet默认配置

DispatcherServlet的默认配置在DispatcherServlet.properties(和DispatcherServlet类在一个包下)中,而且是当Spring配置文件中没有指定配置时使用的默认策略:

 

Java代码  收藏代码
  1. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver  
  2.   
  3. org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver  
  4.   
  5. org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\  
  6.     org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping  
  7.   
  8. org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\  
  9.     org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\  
  10.     org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter  
  11.   
  12. org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\  
  13.     org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\  
  14.     org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver  
  15.   
  16. org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator  
  17.   
  18. org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver  
  19.   
  20. org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager  

   

从如上配置可以看出DispatcherServlet在启动时会自动注册这些特殊的Bean,无需我们注册,如果我们注册了,默认的将不会注册。 

因此如第二章的BeanNameUrlHandlerMapping、SimpleControllerHandlerAdapter是不需要注册的,DispatcherServlet默认会注册这两个Bean。

 

从DispatcherServlet.properties可以看出有许多特殊的Bean,那接下来我们就看看Spring Web MVC主要有哪些特殊的Bean。

3.6、DispatcherServlet中使用的特殊的Bean

DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean:

1、Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;

2、HandlerMapping:请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;

3、HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理;

4、ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;

5、LocalResover:本地化解析,因为Spring支持国际化,因此LocalResover解析客户端的Locale信息从而方便进行国际化;

6、ThemeResovler:主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

7、MultipartResolver:文件上传解析,用于支持文件上传;

8、HandlerExceptionResolver:处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);

9、RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;

10、FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景,后边会细述。

  

到此DispatcherServlet我们已经了解了,接下来我们就需要把上边提到的特殊Bean挨个击破,那首先从控制器开始吧。

 

==========================以上部分来自跟开涛学MVC==================================

==================================哥是分割线========================================

 

 主要方法和类分析:

DispatcherServlet启动时,会依次加载配置文件中所有的Resolver(包括MultipartResolver,LocaleResolver,ThemeResolver)、HandlerMappings、HandlerAdapter、HandlerExceptionResolver、ViewResolver,若没有,则会提供默认的相应配置

 如:

Java代码  收藏代码
  1. protected void initStrategies(ApplicationContext context) {  
  2.         initMultipartResolver(context);  
  3.         initLocaleResolver(context);  
  4.         initThemeResolver(context);  
  5.         initHandlerMappings(context);  
  6.         initHandlerAdapters(context);  
  7.         initHandlerExceptionResolvers(context);  
  8.         initRequestToViewNameTranslator(context);  
  9.         initViewResolvers(context);  
  10.         initFlashMapManager(context);  
  11.     }  

 

 其中,这三个Resolver(MultipartResolver,LocaleResolver,ThemeResolver)是直接通过bean加载

 

Java代码  收藏代码
  1. private void initLocaleResolver(ApplicationContext context) {  
  2.         try {  
  3.             this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);  
  4.             if (logger.isDebugEnabled()) {  
  5.                 logger.debug("Using LocaleResolver [" + this.localeResolver + "]");  
  6.             }  
  7.         }  
  8.         catch (NoSuchBeanDefinitionException ex) {  
  9.             // We need to use the default.  
  10.             this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);  
  11.             if (logger.isDebugEnabled()) {  
  12.                 logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME +  
  13.                         "': using default [" + this.localeResolver + "]");  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18. public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";  

 

而HandlerMappings、HandlerAdapters、HandlerExceptionResolvers则是通过通用方法构造一个相应的Map,如Map<String, HandlerMapping>,Map<String, HandlerAdapter>等,然后获得所有的handlerMappings / handlerAdapters.. List对象,如:

Java代码  收藏代码
  1. private void initHandlerMappings(ApplicationContext context) {  
  2.         this.handlerMappings = null;  
  3.   
  4.         if (this.detectAllHandlerMappings) {  
  5.             // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.  
  6.             Map<String, HandlerMapping> matchingBeans =  
  7.                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.classtruefalse);  
  8.             if (!matchingBeans.isEmpty()) {  
  9.                 this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());  
  10.                 // We keep HandlerMappings in sorted order.  
  11.                 OrderComparator.sort(this.handlerMappings);  
  12.             }  
  13.         }  
  14.         else {  
  15.             try {  
  16.                 HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);  
  17.                 this.handlerMappings = Collections.singletonList(hm);  
  18.             }  
  19.             catch (NoSuchBeanDefinitionException ex) {  
  20.                 // Ignore, we'll add a default HandlerMapping later.  
  21.             }  
  22.         }  
  23.   
  24.         // Ensure we have at least one HandlerMapping, by registering  
  25.         // a default HandlerMapping if no other mappings are found.  
  26.         if (this.handlerMappings == null) {  
  27.             this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);  
  28.             if (logger.isDebugEnabled()) {  
  29.                 logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");  
  30.             }  
  31.         }  
  32.     }  

 

Java代码  收藏代码
  1. Map<String, HandlerAdapter> matchingBeans =  
  2.                     BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.classtruefalse);  
  3.   
  4. Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils  
  5.                     .beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.classtruefalse);  

 当没有找到HandlerMapping等时,会从DispatcherServlet.properties找到一个默认的Mapping,另两个也是

Java代码  收藏代码
  1. private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";     
  2.     private static final Properties defaultStrategies;  
  3.           
  4.     static {  
  5.         // Load default strategy implementations from properties file.  
  6.         // This is currently strictly internal and not meant to be customized  
  7.         // by application developers.  
  8.         try {  
  9.             ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);  
  10.             defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);  
  11.         }  
  12.         catch (IOException ex) {  
  13.             throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());  
  14.         }  
  15.     }  

 

Java代码  收藏代码
  1. // Ensure we have at least one HandlerMapping, by registering  
  2.         // a default HandlerMapping if no other mappings are found.  
  3.         if (this.handlerMappings == null) {  
  4.             this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);  
  5.             if (logger.isDebugEnabled()) {  
  6.                 logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");  
  7.             }  
  8.         }  

 

Java代码  收藏代码
  1. /** 
  2.      * Create a List of default strategy objects for the given strategy interface. 
  3.      * <p>The default implementation uses the "DispatcherServlet.properties" file (in the same 
  4.      * package as the DispatcherServlet class) to determine the class names. It instantiates 
  5.      * the strategy objects through the context's BeanFactory. 
  6.      * @param context the current WebApplicationContext 
  7.      * @param strategyInterface the strategy interface 
  8.      * @return the List of corresponding strategy objects 
  9.      */  
  10.     @SuppressWarnings("unchecked")  
  11.     protected <T> List<T> getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface) {  
  12.         String key = strategyInterface.getName();  
  13.         String value = defaultStrategies.getProperty(key);  
  14.         if (value != null) {  
  15.             String[] classNames = StringUtils.commaDelimitedListToStringArray(value);  
  16.             List<T> strategies = new ArrayList<T>(classNames.length);  
  17.             for (String className : classNames) {  
  18.                 try {  
  19.                     Class<?> clazz = ClassUtils.forName(className, DispatcherServlet.class.getClassLoader());  
  20.                     Object strategy = createDefaultStrategy(context, clazz);  
  21.                     strategies.add((T) strategy);  
  22.                 }  
  23.                 catch (ClassNotFoundException ex) {  
  24.                     throw new BeanInitializationException(  
  25.                             "Could not find DispatcherServlet's default strategy class [" + className +  
  26.                                     "] for interface [" + key + "]", ex);  
  27.                 }  
  28.                 catch (LinkageError err) {  
  29.                     throw new BeanInitializationException(  
  30.                             "Error loading DispatcherServlet's default strategy class [" + className +  
  31.                                     "] for interface [" + key + "]: problem with class file or dependent class", err);  
  32.                 }  
  33.             }  
  34.             return strategies;  
  35.         }  
  36.         else {  
  37.             return new LinkedList<T>();  
  38.         }  
  39.     }  

 

Java代码  收藏代码
  1. /** 
  2.      * Create a default strategy. 
  3.      * <p>The default implementation uses {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean}. 
  4.      * @param context the current WebApplicationContext 
  5.      * @param clazz the strategy implementation class to instantiate 
  6.      * @return the fully configured strategy instance 
  7.      * @see org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory() 
  8.      * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean 
  9.      */  
  10.     protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {  
  11.         return context.getAutowireCapableBeanFactory().createBean(clazz);  
  12.     }  

 

 DispatcherServlet中最主要的核心功能是由doServicedoDispatch实现的。

 

当请求到达后HttpServlet将调用service方法进行处理,由于我们是通过输入网址方式的get方法请求,Servlet将调用doGet方法

此处的doGet方法在FrameworkServlet中实现,doGet方法调用processRequest方法,

processRequest则调用doService方法处理,而doService在DispatcherServlet中实现,

doService再调用了DispatcherServlet的doDispatch方法,该方法则会根据request找到转发对象,并进行请求转发操作,

dispatcherservlet中无论是通过post方式还是get方式提交的request,最终都会交由doservice()处理。

 

具体流程如下:

 

Java代码  收藏代码
  1. //HttpServlet  
  2. protected void service(HttpServletRequest req, HttpServletResponse resp)  
  3.         throws ServletException, IOException  
  4.     {  
  5.         String method = req.getMethod();  
  6.   
  7.         if (method.equals(METHOD_GET)) {  
  8.             long lastModified = getLastModified(req);  
  9.             if (lastModified == -1) {  
  10.                 // servlet doesn't support if-modified-since, no reason  
  11.                 // to go through further expensive logic  
  12.                 doGet(req, resp);  
  13.             } else {  
  14.                 long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);  
  15.                 if (ifModifiedSince < lastModified) {  
  16.                     // If the servlet mod time is later, call doGet()  
  17.                     // Round down to the nearest second for a proper compare  
  18.                     // A ifModifiedSince of -1 will always be less  
  19.                     maybeSetLastModified(resp, lastModified);  
  20.                     doGet(req, resp);  
  21.                 } else {  
  22.                     resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);  
  23.                 }  
  24.             }  
  25.   
  26.         } else if (method.equals(METHOD_HEAD)) {  
  27.             long lastModified = getLastModified(req);  
  28.             maybeSetLastModified(resp, lastModified);  
  29.             doHead(req, resp);  
  30.   
  31.         } else if (method.equals(METHOD_POST)) {  
  32.             doPost(req, resp);  
  33.               
  34.         } else if (method.equals(METHOD_PUT)) {  
  35.             doPut(req, resp);  
  36.               
  37.         } else if (method.equals(METHOD_DELETE)) {  
  38.             doDelete(req, resp);  
  39.               
  40.         } else if (method.equals(METHOD_OPTIONS)) {  
  41.             doOptions(req,resp);  
  42.               
  43.         } else if (method.equals(METHOD_TRACE)) {  
  44.             doTrace(req,resp);  
  45.               
  46.         } else {  
  47.             //  
  48.             // Note that this means NO servlet supports whatever  
  49.             // method was requested, anywhere on this server.  
  50.             //  
  51.   
  52.             String errMsg = lStrings.getString("http.method_not_implemented");  
  53.             Object[] errArgs = new Object[1];  
  54.             errArgs[0] = method;  
  55.             errMsg = MessageFormat.format(errMsg, errArgs);  
  56.               
  57.             resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);  
  58.         }  
  59.     }  

 

Java代码  收藏代码
  1. //FrameworkServlet  
  2.   
  3. @Override  
  4.     protected final void doGet(HttpServletRequest request, HttpServletResponse response)  
  5.             throws ServletException, IOException {  
  6.   
  7.         processRequest(request, response);  
  8.     }  
  9.   
  10. protected final void processRequest(HttpServletRequest request, HttpServletResponse response)  
  11.             throws ServletException, IOException {  
  12.   
  13.         long startTime = System.currentTimeMillis();  
  14.         Throwable failureCause = null;  
  15.   
  16.         LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();  
  17.         LocaleContext localeContext = buildLocaleContext(request);  
  18.   
  19.         RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();  
  20.         ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);  
  21.   
  22.         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
  23.         asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());  
  24.   
  25.         initContextHolders(request, localeContext, requestAttributes);  
  26.   
  27.         try {  
  28.             doService(request, response);  
  29.         }  
  30.         catch (ServletException ex) {  
  31.             failureCause = ex;  
  32.             throw ex;  
  33.         }  
  34.         catch (IOException ex) {  
  35.             failureCause = ex;  
  36.             throw ex;  
  37.         }  
  38.         catch (Throwable ex) {  
  39.             failureCause = ex;  
  40.             throw new NestedServletException("Request processing failed", ex);  
  41.         }  
  42.   
  43.         finally {  
  44.             resetContextHolders(request, previousLocaleContext, previousAttributes);  
  45.             if (requestAttributes != null) {  
  46.                 requestAttributes.requestCompleted();  
  47.             }  
  48.   
  49.             if (logger.isDebugEnabled()) {  
  50.                 if (failureCause != null) {  
  51.                     this.logger.debug("Could not complete request", failureCause);  
  52.                 }  
  53.                 else {  
  54.                     if (asyncManager.isConcurrentHandlingStarted()) {  
  55.                         logger.debug("Leaving response open for concurrent processing");  
  56.                     }  
  57.                     else {  
  58.                         this.logger.debug("Successfully completed request");  
  59.                     }  
  60.                 }  
  61.             }  
  62.   
  63.             publishRequestHandledEvent(request, startTime, failureCause);  
  64.         }  
  65.     }  

 

 DispatcherServlet中doService:

Java代码  收藏代码
  1. @Override  
  2.     protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  3.         if (logger.isDebugEnabled()) {  
  4.             String requestUri = urlPathHelper.getRequestUri(request);  
  5.             String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult() ? " resumed" : "";  
  6.             logger.debug("DispatcherServlet with name '" + getServletName() + "'" + resumed +  
  7.                     " processing " + request.getMethod() + " request for [" + requestUri + "]");  
  8.         }  
  9.   
  10.         // Keep a snapshot of the request attributes in case of an include,  
  11.         // to be able to restore the original attributes after the include.  
  12.         Map<String, Object> attributesSnapshot = null;  
  13.         if (WebUtils.isIncludeRequest(request)) {  
  14.             logger.debug("Taking snapshot of request attributes before include");  
  15.             attributesSnapshot = new HashMap<String, Object>();  
  16.             Enumeration<?> attrNames = request.getAttributeNames();  
  17.             while (attrNames.hasMoreElements()) {  
  18.                 String attrName = (String) attrNames.nextElement();  
  19.                 if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {  
  20.                     attributesSnapshot.put(attrName, request.getAttribute(attrName));  
  21.                 }  
  22.             }  
  23.         }  
  24.   
  25.         // Make framework objects available to handlers and view objects.  
  26.         request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());  
  27.         request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);  
  28.         request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);  
  29.         request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());  
  30.   
  31.         FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);  
  32.         if (inputFlashMap != null) {  
  33.             request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));  
  34.         }  
  35.         request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());  
  36.         request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);  
  37.   
  38.         try {  
  39.             doDispatch(request, response);  
  40.         }  
  41.         finally {  
  42.             if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {  
  43.                 return;  
  44.             }  
  45.             // Restore the original attribute snapshot, in case of an include.  
  46.             if (attributesSnapshot != null) {  
  47.                 restoreAttributesAfterInclude(request, attributesSnapshot);  
  48.             }  
  49.         }  
  50.     }  

 

 doDispatch方法:处理拦截,转发请求,并绘制VIEW

 

 doDispatch()中的处理逻辑大致分以下几个步骤:

1.根据request得到相应的处理器

 HandlerExecutionChain  mappedhandler = getHandler(request)

2.调用注册的所有拦截器的prehandle方法

if (!mappedHandler.applyPreHandle(processedRequest, response))

 

3.调用处理器 

 

//这里使用了adapter模式

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

 

4.调用注册的所有拦截器的posthandle方法

mappedHandler.applyPostHandle(processedRequest, response, mv);

 

5.绘制mv

render(mv, request, response);

 

Java代码  收藏代码
  1. protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  2.         HttpServletRequest processedRequest = request;  
  3.         HandlerExecutionChain mappedHandler = null;  
  4.         boolean multipartRequestParsed = false;  
  5.   
  6.         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);  
  7.   
  8.         try {  
  9.             ModelAndView mv = null;  
  10.             Exception dispatchException = null;  
  11.   
  12.             try {  
  13.                 processedRequest = checkMultipart(request);  
  14.                 multipartRequestParsed = processedRequest != request;  
  15.   
  16.                 // Determine handler for the current request.  
  17.                 mappedHandler = getHandler(processedRequest);  
  18.                 if (mappedHandler == null || mappedHandler.getHandler() == null) {  
  19.                     noHandlerFound(processedRequest, response);  
  20.                     return;  
  21.                 }  
  22.   
  23.                 // Determine handler adapter for the current request.  
  24.                 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  
  25.   
  26.                 // Process last-modified header, if supported by the handler.  
  27.                 String method = request.getMethod();  
  28.                 boolean isGet = "GET".equals(method);  
  29.                 if (isGet || "HEAD".equals(method)) {  
  30.                     long lastModified = ha.getLastModified(request, mappedHandler.getHandler());  
  31.                     if (logger.isDebugEnabled()) {  
  32.                         String requestUri = urlPathHelper.getRequestUri(request);  
  33.                         logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);  
  34.                     }  
  35.                     if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {  
  36.                         return;  
  37.                     }  
  38.                 }  
  39.   
  40.                 if (!mappedHandler.applyPreHandle(processedRequest, response)) {  
  41.                     return;  
  42.                 }  
  43.   
  44.                 try {  
  45.                     // Actually invoke the handler.  
  46.                     mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  
  47.                 }  
  48.                 finally {  
  49.                     if (asyncManager.isConcurrentHandlingStarted()) {  
  50.                         return;  
  51.                     }  
  52.                 }  
  53.   
  54.                 applyDefaultViewName(request, mv);  
  55.                 mappedHandler.applyPostHandle(processedRequest, response, mv);  
  56.             }  
  57.             catch (Exception ex) {  
  58.                 dispatchException = ex;  
  59.             }  
  60.             processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);  
  61.         }  
  62.         catch (Exception ex) {  
  63.             triggerAfterCompletion(processedRequest, response, mappedHandler, ex);  
  64.         }  
  65.         catch (Error err) {  
  66.             triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);  
  67.         }  
  68.         finally {  
  69.             if (asyncManager.isConcurrentHandlingStarted()) {  
  70.                 // Instead of postHandle and afterCompletion  
  71.                 mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);  
  72.                 return;  
  73.             }  
  74.             // Clean up any resources used by a multipart request.  
  75.             if (multipartRequestParsed) {  
  76.                 cleanupMultipart(processedRequest);  
  77.             }  
  78.         }  
  79.     }  
Java代码  收藏代码
  1. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {  
  2.         for (HandlerMapping hm : this.handlerMappings) {  
  3.             if (logger.isTraceEnabled()) {  
  4.                 logger.trace(  
  5.                         "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");  
  6.             }  
  7.             HandlerExecutionChain handler = hm.getHandler(request);  
  8.             if (handler != null) {  
  9.                 return handler;  
  10.             }  
  11.         }  
  12.         return null;  
  13.     }  

参考:

SpringMVC中DispatcherServlet工作原理探究

spring中dispatcherservlet的运行机制

 

 几个实例对象:

1个HandlerMapping有1个HandlerExecutionChain

HandlerExecutionChain下有多个过滤器HandlerInterceptor

 

过滤器HandlerInterceptor下有前置方法和后置方法

Java代码  收藏代码
  1. public interface HandlerMapping {  
  2.   
  3.     /** 
  4.      * Return a handler and any interceptors for this request. The choice may be made 
  5.      * on request URL, session state, or any factor the implementing class chooses. 
  6.      * <p>The returned HandlerExecutionChain contains a handler Object, rather than 
  7.      * even a tag interface, so that handlers are not constrained in any way.     
  8.      */  
  9.     HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;  
  10.   
  11. }  

 

Java代码  收藏代码
  1. public class HandlerExecutionChain {  
  2.   
  3.     private final Object handler;  
  4.   
  5.     private HandlerInterceptor[] interceptors;  
  6.   
  7.     private List<HandlerInterceptor> interceptorList;  
  8.   
  9.     private int interceptorIndex = -1;  
  10.   
  11.   
  12.     public HandlerExecutionChain(Object handler) {  
  13.         this(handler, null);  
  14.     }  
  15.   
  16.     public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) {  
  17.         if (handler instanceof HandlerExecutionChain) {  
  18.             HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;  
  19.             this.handler = originalChain.getHandler();  
  20.             this.interceptorList = new ArrayList<HandlerInterceptor>();  
  21.             CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);  
  22.             CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);  
  23.         }  
  24.         else {  
  25.             this.handler = handler;  
  26.             this.interceptors = interceptors;  
  27.         }  
  28.     }  
  29.       
  30.     public Object getHandler() {  
  31.         return this.handler;  
  32.     }  
  33.   
  34.     public void addInterceptor(HandlerInterceptor interceptor) {  
  35.         initInterceptorList();  
  36.         this.interceptorList.add(interceptor);  
  37.     }  
  38.   
  39.     public void addInterceptors(HandlerInterceptor[] interceptors) {  
  40.         if (interceptors != null) {  
  41.             initInterceptorList();  
  42.             this.interceptorList.addAll(Arrays.asList(interceptors));  
  43.         }  
  44.     }  
  45.   
  46.     private void initInterceptorList() {  
  47.         if (this.interceptorList == null) {  
  48.             this.interceptorList = new ArrayList<HandlerInterceptor>();  
  49.         }  
  50.         if (this.interceptors != null) {  
  51.             this.interceptorList.addAll(Arrays.asList(this.interceptors));  
  52.             this.interceptors = null;  
  53.         }  
  54.     }  
  55.   
  56.     /** 
  57.      * Return the array of interceptors to apply (in the given order). 
  58.      * @return the array of HandlerInterceptors instances (may be {@code null}) 
  59.      */  
  60.     public HandlerInterceptor[] getInterceptors() {  
  61.         if (this.interceptors == null && this.interceptorList != null) {  
  62.             this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);  
  63.         }  
  64.         return this.interceptors;  
  65.     }  
  66.   
  67.     /** 
  68.      * 过滤器前置方法 
  69.      */  
  70.     boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {  
  71.         if (getInterceptors() != null) {  
  72.             for (int i = 0; i < getInterceptors().length; i++) {  
  73.                 HandlerInterceptor interceptor = getInterceptors()[i];  
  74.                 if (!interceptor.preHandle(request, response, this.handler)) {  
  75.                     triggerAfterCompletion(request, response, null);  
  76.                     return false;  
  77.                 }  
  78.                 this.interceptorIndex = i;  
  79.             }  
  80.         }  
  81.         return true;  
  82.     }  
  83.   
  84.     /** 
  85.      * 过滤器后置方法 
  86.      */  
  87.     void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {  
  88.         if (getInterceptors() == null) {  
  89.             return;  
  90.         }  
  91.         for (int i = getInterceptors().length - 1; i >= 0; i--) {  
  92.             HandlerInterceptor interceptor = getInterceptors()[i];  
  93.             interceptor.postHandle(request, response, this.handler, mv);  
  94.         }  
  95.     }  
  96.   
  97.     /** 
  98.      * Trigger afterCompletion callbacks on the mapped HandlerInterceptors. 
  99.      * Will just invoke afterCompletion for all interceptors whose preHandle invocation 
  100.      * has successfully completed and returned true. 
  101.      */  
  102.     void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)  
  103.             throws Exception {  
  104.   
  105.         if (getInterceptors() == null) {  
  106.             return;  
  107.         }  
  108.         for (int i = this.interceptorIndex; i >= 0; i--) {  
  109.             HandlerInterceptor interceptor = getInterceptors()[i];  
  110.             try {  
  111.                 interceptor.afterCompletion(request, response, this.handler, ex);  
  112.             }  
  113.             catch (Throwable ex2) {  
  114.                 logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);  
  115.             }  
  116.         }  
  117.     }  
  118.   
  119.     /** 
  120.      * Apply afterConcurrentHandlerStarted callback on mapped AsyncHandlerInterceptors. 
  121.      */  
  122.     void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {  
  123.         if (getInterceptors() == null) {  
  124.             return;  
  125.         }  
  126.         for (int i = getInterceptors().length - 1; i >= 0; i--) {  
  127.             if (interceptors[i] instanceof AsyncHandlerInterceptor) {  
  128.                 try {  
  129.                     AsyncHandlerInterceptor asyncInterceptor = (AsyncHandlerInterceptor) this.interceptors[i];  
  130.                     asyncInterceptor.afterConcurrentHandlingStarted(request, response, this.handler);  
  131.                 }  
  132.                 catch (Throwable ex) {  
  133.                     logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", ex);  
  134.                 }  
  135.             }  
  136.         }  
  137.     }  
  138.   
  139. }  

   适配器:

Java代码  收藏代码
  1. public interface HandlerAdapter {  
  2.       
  3.     /** 
  4.      * 处理请求Controller业务逻辑 
  5.      */  
  6.     ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;  
  7.   
  8. }  

 

Java代码  收藏代码
  1. public interface HandlerInterceptor {  
  2.   
  3.     /** 
  4.      * Intercept the execution of a handler. Called after HandlerMapping determined 
  5.      * an appropriate handler object, but before HandlerAdapter invokes the handler.  
  6.      */  
  7.     boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  
  8.         throws Exception;  
  9.   
  10.           
  11.     /** 
  12.      * Intercept the execution of a handler. Called after HandlerAdapter actually 
  13.      * invoked the handler, but before the DispatcherServlet renders the view.   
  14.      */  
  15.     void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  
  16.             throws Exception;  
  17.   
  18.     /** 
  19.      * Callback after completion of request processing, that is, after rendering     * 
  20.      */  
  21.     void afterCompletion(  
  22.             HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  
  23.             throws Exception;  
  24.   
  25. }  

 

 

Java代码  收藏代码
  1. // 包含一个View对象和一个Map  
  2. //其中setViewName设置逻辑视图名,视图解析器会根据该名字解析到具体的视图页面  
  3. public class ModelAndView {  
  4.   
  5.     private Object view;  
  6.   
  7.     private ModelMap model;  
  8.   
  9.       
  10.     public ModelAndView(String viewName) {  
  11.         this.view = viewName;  
  12.     }  
  13.   
  14.     public ModelAndView(View view) {  
  15.         this.view = view;  
  16.     }  
  17.       
  18.     public ModelAndView(String viewName, Map<String, ?> model) {  
  19.         this.view = viewName;  
  20.         if (model != null) {  
  21.             getModelMap().addAllAttributes(model);  
  22.         }  
  23.     }  
  24.       
  25.     public ModelAndView(View view, Map<String, ?> model) {  
  26.         this.view = view;  
  27.         if (model != null) {  
  28.             getModelMap().addAllAttributes(model);  
  29.         }  
  30.     }  
  31.   
  32.     /** 
  33.      * Convenient constructor to take a single model object. 
  34.      * @param viewName name of the View to render, to be resolved 
  35.      * by the DispatcherServlet's ViewResolver 
  36.      * @param modelName name of the single entry in the model 
  37.      * @param modelObject the single model object 
  38.      */  
  39.     public ModelAndView(String viewName, String modelName, Object modelObject) {  
  40.         this.view = viewName;  
  41.         addObject(modelName, modelObject);  
  42.     }  
  43.   
  44.     /** 
  45.      * Convenient constructor to take a single model object. 
  46.      * @param view View object to render 
  47.      * @param modelName name of the single entry in the model 
  48.      * @param modelObject the single model object 
  49.      */  
  50.     public ModelAndView(View view, String modelName, Object modelObject) {  
  51.         this.view = view;  
  52.         addObject(modelName, modelObject);  
  53.     }  
  54.   
  55.   
  56.     /** 
  57.      * Set a view name for this ModelAndView, to be resolved by the 
  58.      * DispatcherServlet via a ViewResolver. Will override any 
  59.      * pre-existing view name or View. 
  60.      */  
  61.     public void setViewName(String viewName) {  
  62.         this.view = viewName;  
  63.     }  
  64.   
  65.     /** 
  66.      * Return the view name to be resolved by the DispatcherServlet 
  67.      * via a ViewResolver, or {@code null} if we are using a View object. 
  68.      */  
  69.     public String getViewName() {  
  70.         return (this.view instanceof String ? (String) this.view : null);  
  71.     }  
  72.   
  73.     /** 
  74.      * Set a View object for this ModelAndView. Will override any 
  75.      * pre-existing view name or View. 
  76.      */  
  77.     public void setView(View view) {  
  78.         this.view = view;  
  79.     }  
  80.   
  81.     /** 
  82.      * Return the View object, or {@code null} if we are using a view name 
  83.      * to be resolved by the DispatcherServlet via a ViewResolver. 
  84.      */  
  85.     public View getView() {  
  86.         return (this.view instanceof View ? (View) this.view : null);  
  87.     }  
  88.   
  89.     /** 
  90.      * Indicate whether or not this {@code ModelAndView} has a view, either 
  91.      * as a view name or as a direct {@link View} instance. 
  92.      */  
  93.     public boolean hasView() {  
  94.         return (this.view != null);  
  95.     }  
  96.   
  97.     /** 
  98.      * Return whether we use a view reference, i.e. {@code true} 
  99.      * if the view has been specified via a name to be resolved by the 
  100.      * DispatcherServlet via a ViewResolver. 
  101.      */  
  102.     public boolean isReference() {  
  103.         return (this.view instanceof String);  
  104.     }  
  105.   
  106.     /** 
  107.      * Return the model map. May return {@code null}. 
  108.      * Called by DispatcherServlet for evaluation of the model. 
  109.      */  
  110.     protected Map<String, Object> getModelInternal() {  
  111.         return this.model;  
  112.     }  
  113.   
  114.     /** 
  115.      * Return the underlying {@code ModelMap} instance (never {@code null}). 
  116.      */  
  117.     public ModelMap getModelMap() {  
  118.         if (this.model == null) {  
  119.             this.model = new ModelMap();  
  120.         }  
  121.         return this.model;  
  122.     }  
  123.   
  124.     /** 
  125.      * Return the model map. Never returns {@code null}. 
  126.      * To be called by application code for modifying the model. 
  127.      */  
  128.     public Map<String, Object> getModel() {  
  129.         return getModelMap();  
  130.     }  
  131.   
  132.   
  133.     /** 
  134.      * Add an attribute to the model. 
  135.      * @param attributeName name of the object to add to the model 
  136.      * @param attributeValue object to add to the model (never {@code null}) 
  137.      * @see ModelMap#addAttribute(String, Object) 
  138.      * @see #getModelMap() 
  139.      */  
  140.     public ModelAndView addObject(String attributeName, Object attributeValue) {  
  141.         getModelMap().addAttribute(attributeName, attributeValue);  
  142.         return this;  
  143.     }  
  144.   
  145.     /** 
  146.      * Add an attribute to the model using parameter name generation. 
  147.      * @param attributeValue the object to add to the model (never {@code null}) 
  148.      * @see ModelMap#addAttribute(Object) 
  149.      * @see #getModelMap() 
  150.      */  
  151.     public ModelAndView addObject(Object attributeValue) {  
  152.         getModelMap().addAttribute(attributeValue);  
  153.         return this;  
  154.     }  
  155.   
  156.     /** 
  157.      * Add all attributes contained in the provided Map to the model. 
  158.      * @param modelMap a Map of attributeName -> attributeValue pairs 
  159.      * @see ModelMap#addAllAttributes(Map) 
  160.      * @see #getModelMap() 
  161.      */  
  162.     public ModelAndView addAllObjects(Map<String, ?> modelMap) {  
  163.         getModelMap().addAllAttributes(modelMap);  
  164.         return this;  
  165.     }  
  166.   
  167. }  

 

Java代码  收藏代码
  1. public interface ViewResolver {  
  2.   
  3.     /** 
  4.      * Resolve the given view by name. 
  5.      * 从viewName获取View 
  6.      */  
  7.     View resolveViewName(String viewName, Locale locale) throws Exception;  
  8.   
  9. }  

 

Java代码  收藏代码
  1. public interface View {  
  2.   
  3.     /** 
  4.      * Render the view given the specified model. 
  5.      * 渲染页面 
  6.      */  
  7.     void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;  
  8.   
  9. }