• Spring MVC之DispatcherServlet初始化


         使用Spring MVC 时,需要在web.xml中配置DispatchServlet,这个DispatchServlet可以看成一个控制器的具体实现。作为一个控制器所有的请求都要通过它来处理,进行转发、匹配、数据处理后并转由页面进行展示。因此DispatchServlet是Spring MVC的核心部分。    

          在完成ContextLoaderListener的初始化后,Web容器开始初始化DispatcherServlet,这个初始化的启动与在web.xml中对载入次序的定义有关。DispathcerServlet会建立自己的上下文来持有Spring MVC的Bean,在建立这个自己的IOC容器时,会从ServletContext中得到根上下文作为自己持有上下文的双亲上下文。有了这个根上下文再对自己持有的上下文进行初始化,最后将自己持有的上下文保存到ServletContext中。

         首先看看DispatcherSerlvet的继承关系:DispatcherServlet继承自FrameworkServlet,而FrameworkServet继承自HttpServletBean.HttpServletBean有继承了HttpServlet.

        DispatcherServlet动作大致可以分为两个部分:初始化部分由initServletBean()启动,通过initWebApplicationContext()方法调用DispatcherServlet的initStrategies方法。在这个方法里,DispatcherServlet对MVC的其他部分进行了初始化,比如handlerMapping,ViewResolver;另一个部分是对Http的请求进行响应,作为一个Servlet,web容器会调用Servlet的doGet()和doPost()方法,在经过FrameServlet的processRequest()简单处理后,会调用DispatcherServlet的doService()方法,在这个方法中封装了doDispatch().

         在这里主要介绍初始化部分。

        作为Servlet, DispatcherServlet的启动过程和Servlet启动过程是相联系的。在Servlet的初始化过程中,Servlet的init方法被调用,已进行初始化。

    HttppServletBean.init()->FrameworkServlet.initWebApplicationContext()->DispatcherServlet.onRefresh().

    onRefresh 的源码是:

    	/**
    	 * This implementation calls {@link #initStrategies}.
    	 */
    	@Override
    	protected void onRefresh(ApplicationContext context) {
    		initStrategies(context);
    	}

     而initStrategies(context)的源码如下:

    	protected void initStrategies(ApplicationContext context) {
    		//初始化多媒体解析器
    		initMultipartResolver(context);
    		//初始化位置解析器
    		initLocaleResolver(context);
    		//初始化主题解析器
    		initThemeResolver(context);
    		//初始化HandlerMappings
    		initHandlerMappings(context);
    		// 初始化HandlerAdapters
    		initHandlerAdapters(context);
    		//初始化异常解析器
    		initHandlerExceptionResolvers(context);
    		//初始化请求到视图名转换器
    		initRequestToViewNameTranslator(context);
    		//初始化视图解析器
    		initViewResolvers(context);
    		//初始化FlashMapManager
    		initFlashMapManager(context);
    	}

         通过initMultipartResover进行初始化多媒体解析器,如果在配置文件中没有配置id为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");
    			}
    		}
    	}

       通过initLocaleResolver方法进行localeResolver的初始化,如果没有配置指定id为localeResolver的bean则使用AcceptHeaderLocaleResolver的位置解析器。

     * Initialize the LocaleResolver used by this class.
    	 * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
    	 * we default to AcceptHeaderLocaleResolver.
    	 */
    	private void initLocaleResolver(ApplicationContext context) {
    		try {
    			this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Using LocaleResolver [" + this.localeResolver + "]");
    			}
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			// We need to use the default.
    			this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Unable to locate LocaleResolver with name '" + LOCALE_RESOLVER_BEAN_NAME +
    						"': using default [" + this.localeResolver + "]");
    			}
    		}
    	}

     initThemeResolver初始化主题解析器,如果没有配置指定id的为themeResolver的bean 则使用FixedThemeResolver主题解析器

    	/**
    	 * Initialize the ThemeResolver used by this class.
    	 * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
    	 * we default to a FixedThemeResolver.
    	 */
    	private void initThemeResolver(ApplicationContext context) {
    		try {
    			this.themeResolver = context.getBean(THEME_RESOLVER_BEAN_NAME, ThemeResolver.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Using ThemeResolver [" + this.themeResolver + "]");
    			}
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			// We need to use the default.
    			this.themeResolver = getDefaultStrategy(context, ThemeResolver.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug(
    						"Unable to locate ThemeResolver with name '" + THEME_RESOLVER_BEAN_NAME + "': using default [" +
    								this.themeResolver + "]");
    			}
    		}
    	}

     初始化HandlerMapping,这个handlerMapping的作用是为Http请求找到相应的控制器,从而利用这些控制器去完成http请求的数据处理工作。这些控制器和http的请求时对应的。DispatcherServlet中handlerMapping的初始化过程中的具体实现如下。在HandlerMapping的初始化过程中,把Bean配置文件中配置好的handlerMapping从IOC容器中取出。

    	/**
    	 * Initialize the HandlerMappings used by this class.
    	 * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
    	 * we default to BeanNameUrlHandlerMapping.
    	 */
    	private void initHandlerMappings(ApplicationContext context) {
    		this.handlerMappings = null;
    	
    		if (this.detectAllHandlerMappings) {
    			// 在应用上下文包括其祖先上下文中查找所有HandlerMappings
    			Map<String, HandlerMapping> matchingBeans =
    					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
    			//如果matchingBeans这个map是不为空,则创建一个新的ArrayList
    			if (!matchingBeans.isEmpty()) {
    				this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
    				//并对其进行排序
    				OrderComparator.sort(this.handlerMappings);
    			}
    		}
    		else {
    			try {
    			    //从应用上下文中查找所有的HandlerMapping
    				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.
    		if (this.handlerMappings == null) {
    			// 如果没有配置HandlerMapping 则使用默认的HandlerMapping 策略
    			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
    			}
    		}
    	}
    

         进过上述的处理过程,handlerMapping已经初始化完成,handlerMapping中就已经获取了在BeanDefinition中配置的映射关系。

          通过initHandlerAdapters进行初始化HandlerAdapter,如果没有配置HandlerAdapter则使用SimpleControllerHandlerAdapter

    /**
    	 * Initialize the HandlerAdapters used by this class.
    	 * <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,
    	 * we default to SimpleControllerHandlerAdapter.
    	 */
    	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<HandlerAdapter>(matchingBeans.values());
    				// We keep HandlerAdapters in sorted order.
    				OrderComparator.sort(this.handlerAdapters);
    			}
    		}
    		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");
    			}
    		}
    	}
    

      初始化异常处理器,如果没有配置指定Id为handlerExceptionResolver的Bean,默认是没有异常处理器

    	/**
    	 * Initialize the HandlerExceptionResolver used by this class.
    	 * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
    	 * we default to no exception resolver.
    	 */
    	private void initHandlerExceptionResolvers(ApplicationContext context) {
    		this.handlerExceptionResolvers = null;
    
    		if (this.detectAllHandlerExceptionResolvers) {
    			// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
    			Map<String, HandlerExceptionResolver> matchingBeans = BeanFactoryUtils
    					.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
    			if (!matchingBeans.isEmpty()) {
    				this.handlerExceptionResolvers = new ArrayList<HandlerExceptionResolver>(matchingBeans.values());
    				// We keep HandlerExceptionResolvers in sorted order.
    				OrderComparator.sort(this.handlerExceptionResolvers);
    			}
    		}
    		else {
    			try {
    				HandlerExceptionResolver her =
    						context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
    				this.handlerExceptionResolvers = Collections.singletonList(her);
    			}
    			catch (NoSuchBeanDefinitionException ex) {
    				// Ignore, no HandlerExceptionResolver is fine too.
    			}
    		}
    
    		// Ensure we have at least some HandlerExceptionResolvers, by registering
    		// default HandlerExceptionResolvers if no other resolvers are found.
    		if (this.handlerExceptionResolvers == null) {
    			this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");
    			}
    		}
    	}

    初始化请求到视图名称的转换器,如果不配置则使用默认的转换器。

    /**
    	 * Initialize the RequestToViewNameTranslator used by this servlet instance.
    	 * <p>If no implementation is configured then we default to DefaultRequestToViewNameTranslator.
    	 */
    	private void initRequestToViewNameTranslator(ApplicationContext context) {
    		try {
    			this.viewNameTranslator =
    					context.getBean(REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME, RequestToViewNameTranslator.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Using RequestToViewNameTranslator [" + this.viewNameTranslator + "]");
    			}
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			// We need to use the default.
    			this.viewNameTranslator = getDefaultStrategy(context, RequestToViewNameTranslator.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Unable to locate RequestToViewNameTranslator with name '" +
    						REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME + "': using default [" + this.viewNameTranslator +
    						"]");
    			}
    		}
    	}
    

      初始化视图解析器,如果没有配置视图解析器则使用默认的InternalResourceViewResolver视图解析器

    /**
    	 * Initialize the ViewResolvers used by this class.
    	 * <p>If no ViewResolver beans are defined in the BeanFactory for this
    	 * namespace, we default to InternalResourceViewResolver.
    	 */
    	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<ViewResolver>(matchingBeans.values());
    				// We keep ViewResolvers in sorted order.
    				OrderComparator.sort(this.viewResolvers);
    			}
    		}
    		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");
    			}
    		}
    	}
    

     获取默认设置,首先获取接口的名称,然后从DispatcherServlert.properties的配置文件中读取value,然后将其分割为字符串数组。

    /**
    	 * Create a List of default strategy objects for the given strategy interface.
    	 * <p>The default implementation uses the "DispatcherServlet.properties" file (in the same
    	 * package as the DispatcherServlet class) to determine the class names. It instantiates
    	 * the strategy objects through the context's BeanFactory.
    	 * @param context the current WebApplicationContext
    	 * @param strategyInterface the strategy interface
    	 * @return the List of corresponding strategy objects
    	 */
    	@SuppressWarnings("unchecked")
    	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<T>(classNames.length);
    			for (String className : classNames) {
    				try {
    					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(
    							"Error loading DispatcherServlet's default strategy class [" + className +
    									"] for interface [" + key + "]: problem with class file or dependent class", err);
    				}
    			}
    			return strategies;
    		}
    		else {
    			return new LinkedList<T>();
    		}
    	}

    DispatcherSerlvet.properties

        # Default implementation classes for DispatcherServlet's strategy interfaces.
    # Used as fallback when no matching beans are found in the DispatcherServlet context.
    # Not meant to be customized by application developers.
    
    org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
    
    org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
    
    org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
    	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
    
    org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,
    	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,
    	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
    
    org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,
    	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,
    	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
    
    org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
    
    org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
    
    org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
  • 相关阅读:
    表达式目录树(Expression)
    六大设计原则【单一职责】【里氏替换】【 迪米特法则】【依赖倒置原则】【接口隔离原则】【开闭原则】
    lambda,linq
    c#中的特性Attribute
    CentOS7部署Nginx
    NetCore项目的部署
    ABP+NetCore+Vue.js实现增删改查
    Abp数据库迁移注意事项
    MVC分页
    AspNet5 Changes to [Activate] in beta-5
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797809.html
Copyright © 2020-2023  润新知