zoukankan      html  css  js  c++  java
  • Spring之SpringMVC(源码)初始化DispatcherServlet策略配置

    1.从上一篇文章中可以SpringMVC初始化的过程中完成的其中一件事就是DispatcherServlet的相关策略的配置,如下所示

    	protected void initStrategies(ApplicationContext context) {
    		initMultipartResolver(context);
    		initLocaleResolver(context);
    		initThemeResolver(context);
    		initHandlerMappings(context);
    		initHandlerAdapters(context);
    		initHandlerExceptionResolvers(context);
    		initRequestToViewNameTranslator(context);
    		initViewResolvers(context);
    		initFlashMapManager(context);
    	}
    

      下面分别看下,每个策略配置的具体实现

    2.文件类型解析器

    	private void initMultipartResolver(ApplicationContext context) {
    		try {
                  //public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver" 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"); } } }

      通过初始化这个类来处理文件解析,但是也可以发现如果没有提供的话,就会给出一个空的的解析器。

    3. LocaleResolver解析器

    	private void initLocaleResolver(ApplicationContext context) {
    		try {// public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
    			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 + "]");
    			}
    		}
    	}
    

      

    为了让web应用程序支持国际化,必须识别每个用户的首选区域,并根据这个区域显示内容。LocaleResolver解析器主要解决国际化的问题。如果配置了那么就使用所配置的解析器,如果没有配置的话,那么就是用默认提供的AcceptHeaderLocaleResolver。

    4.ThemeResolver

    主题样式解析器,

    	private void initThemeResolver(ApplicationContext context) {
    		try {// public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
    			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 + "]");
    			}
    		}
    	}
    

      如果提供了提供了相应的主题解析器,那么就是用,否则的话就是提供一个默认的FixedThemeResolver来作为主题解析器,

    5.处理器映射解析器

    	private void initHandlerMappings(ApplicationContext context) {
    		this.handlerMappings = null;
    
    		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<HandlerMapping>(matchingBeans.values());
    				// We keep HandlerMappings in sorted order.
    				OrderComparator.sort(this.handlerMappings);
    			}
    		}
    		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.
    			}
    		}
    

      请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;通过这个类来初始化HandlerMappings,主要完成请求和处理器之间的映射关系。如果没有提供的话那么就会使用默认的BeanNameUrlHandlerMapping来进项相关的处理。我们来看下大致的处理过程。首先会获取所有的处理映射,然后对这些请求映射进项排序;如果请求映射集合为空,那么就会找到系统中的HandlerMapping,并且进行单例操作处理。如果这个HandlerMapping对象为空,就会使用默认的HandlerMapping,也就是BeanNameUrlHandlerMapping。

    6.handlerAdapter解析器

    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");
    			}
    		}
    	}
    

      HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器。也就是说按照特定规则(HandlerAdapter要求的规则)去执行Handler。它会首先获取ApplicationContext中所有的处理适配器,如果获取集合不为空,需要进行排序处理。没有找到,则会查找系统中的handlerAdapter,然后进行单例化处理。如果查找的系统handlerAdapter为空,则使用默认的适配器,也即是SimpleControllerHandlerAdapter,它将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理。

    7.HandlerExceptionResolver

    	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");
    			}
    		}
    	}
    

      通过这个方法来初始化HandlerExceptionResolver,如果没有配置,系统默认不会提供处理器异常解析器,会给一个空的来作为默认。它首先会查找ApplicationContext中所有的配置的处理器异常解析器,包括它的父容器的范围的,如果找到了会进行有序处理操作( Map<String, HandlerExceptionResolver>);如果找不到具体的映射配置,那么就会获取ApplicationContext中的HandlerExceptionResolver并且进行单例化处理。如果获取的这个解析器为空,那么就会使用默认的,也就是空的解析器处理。

    8.RequestToViewNameTranslator

    	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 +
    						"]");
    			}
    		}
    	}
    

    通过提供的 Servlet实例来初始化RequestToViewNameTranslator,如果没有提供的话,就会使用系统默认的DefaultRequestToViewNameTranslator。

    9.视图解析器

    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");
    			}
    		}
    	}
    

    通过这个来进行视图解析器的初始化工作,如果没有提供的话那么就会使用InternalResourceViewResolver来进行处理,是不是对JSP页面处理的时候经常看到这个配置。

    10.FlashMapManager

    	private void initFlashMapManager(ApplicationContext context) {
    		try {
    			this.flashMapManager =
    					context.getBean(FLASH_MAP_MANAGER_BEAN_NAME, FlashMapManager.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Using FlashMapManager [" + this.flashMapManager + "]");
    			}
    		}
    		catch (NoSuchBeanDefinitionException ex) {
    			// We need to use the default.
    			this.flashMapManager = getDefaultStrategy(context, FlashMapManager.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("Unable to locate FlashMapManager with name '" +
    						FLASH_MAP_MANAGER_BEAN_NAME + "': using default [" + this.flashMapManager + "]");
    			}
    		}
    	}
    

      从方法中的注释可知,如果用户没有提供它的配置,那么就是使用spring提供的org.springframework.web.servlet.support.DefaultFlashMapManager来作为默认的处理。

    11.常量配置

    11.1关于上面的初始化的配置常量

    	/** Well-known name for the MultipartResolver object in the bean factory for this namespace. */
    	public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
    
    	/** Well-known name for the LocaleResolver object in the bean factory for this namespace. */
    	public static final String LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
    
    	/** Well-known name for the ThemeResolver object in the bean factory for this namespace. */
    	public static final String THEME_RESOLVER_BEAN_NAME = "themeResolver";
    
    	/**
    	 * Well-known name for the HandlerMapping object in the bean factory for this namespace.
    	 * Only used when "detectAllHandlerMappings" is turned off.
    	 * @see #setDetectAllHandlerMappings
    	 */
    	public static final String HANDLER_MAPPING_BEAN_NAME = "handlerMapping";
    
    	/**
    	 * Well-known name for the HandlerAdapter object in the bean factory for this namespace.
    	 * Only used when "detectAllHandlerAdapters" is turned off.
    	 * @see #setDetectAllHandlerAdapters
    	 */
    	public static final String HANDLER_ADAPTER_BEAN_NAME = "handlerAdapter";
    
    	/**
    	 * Well-known name for the HandlerExceptionResolver object in the bean factory for this namespace.
    	 * Only used when "detectAllHandlerExceptionResolvers" is turned off.
    	 * @see #setDetectAllHandlerExceptionResolvers
    	 */
    	public static final String HANDLER_EXCEPTION_RESOLVER_BEAN_NAME = "handlerExceptionResolver";
    
    	/**
    	 * Well-known name for the RequestToViewNameTranslator object in the bean factory for this namespace.
    	 */
    	public static final String REQUEST_TO_VIEW_NAME_TRANSLATOR_BEAN_NAME = "viewNameTranslator";
    
    	/**
    	 * Well-known name for the ViewResolver object in the bean factory for this namespace.
    	 * Only used when "detectAllViewResolvers" is turned off.
    	 * @see #setDetectAllViewResolvers
    	 */
    	public static final String VIEW_RESOLVER_BEAN_NAME = "viewResolver";
    
    	/**
    	 * Well-known name for the FlashMapManager object in the bean factory for this namespace.
    	 */
    	public static final String FLASH_MAP_MANAGER_BEAN_NAME = "flashMapManager";
    
    	/**
    	 * Request attribute to hold the current web application context.
    	 * Otherwise only the global web app context is obtainable by tags etc.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getWebApplicationContext
    	 */
    	public static final String WEB_APPLICATION_CONTEXT_ATTRIBUTE = DispatcherServlet.class.getName() + ".CONTEXT";
    
    	/**
    	 * Request attribute to hold the current LocaleResolver, retrievable by views.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getLocaleResolver
    	 */
    	public static final String LOCALE_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".LOCALE_RESOLVER";
    
    	/**
    	 * Request attribute to hold the current ThemeResolver, retrievable by views.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getThemeResolver
    	 */
    	public static final String THEME_RESOLVER_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_RESOLVER";
    
    	/**
    	 * Request attribute to hold the current ThemeSource, retrievable by views.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getThemeSource
    	 */
    	public static final String THEME_SOURCE_ATTRIBUTE = DispatcherServlet.class.getName() + ".THEME_SOURCE";
    
    	/**
    	 * Name of request attribute that holds a read-only {@code Map<String,?>}
    	 * with "input" flash attributes saved by a previous request, if any.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getInputFlashMap(HttpServletRequest)
    	 */
    	public static final String INPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".INPUT_FLASH_MAP";
    
    	/**
    	 * Name of request attribute that holds the "output" {@link FlashMap} with
    	 * attributes to save for a subsequent request.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getOutputFlashMap(HttpServletRequest)
    	 */
    	public static final String OUTPUT_FLASH_MAP_ATTRIBUTE = DispatcherServlet.class.getName() + ".OUTPUT_FLASH_MAP";
    
    	/**
    	 * Name of request attribute that holds the {@link FlashMapManager}.
    	 * @see org.springframework.web.servlet.support.RequestContextUtils#getFlashMapManager(HttpServletRequest)
    	 */
    	public static final String FLASH_MAP_MANAGER_ATTRIBUTE = DispatcherServlet.class.getName() + ".FLASH_MAP_MANAGER";
    
    	/** Log category to use when no mapped handler is found for a request. */
    	public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
    
    	/**
    	 * Name of the class path resource (relative to the DispatcherServlet class)
    	 * that defines DispatcherServlet's default strategy names.
    	 */
    	private static final String DEFAULT_STRATEGIES_PATH = "DispatcherServlet.properties";
    

      11.2Spring提供的默认配置文件DispatcherServlet.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
    

      有上面的SpringMVC默认的配置文件可知,相应的策略实现有系统默认的配置项。

  • 相关阅读:
    Javascript 中的浮点数精度丢失问题
    react中使用字符串中生成HTML
    前端-HTML规范
    js 数组(Array)的使用
    ES6变量声明解析
    cookies sessionlStorage和localStroage的区别
    面向对象
    迭代器、生成器、装饰器
    内置函数和文件读取
    函数
  • 原文地址:https://www.cnblogs.com/zhangminghui/p/4913089.html
Copyright © 2011-2022 走看看