• SpringMVC源码情操陶冶-DispatcherServlet类简析(一)


    阅读源码有利于陶冶情操,此文承接前文SpringMVC源码情操陶冶-DispatcherServlet父类简析
    注意:springmvc初始化其他内容,其对应的配置文件已被加载至beanFactory中

    DispatcherServlet#静态方法

    DispatcherServlet静态块读取DispatcherServlet.properties,其中包含默认的策略实现

    static {
    		// Load default strategy implementations from properties file.
    		// This is currently strictly internal and not meant to be customized
    		// by application developers.
    		try {
    			ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, DispatcherServlet.class);
    			defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    		}
    		catch (IOException ex) {
    			throw new IllegalStateException("Could not load 'DispatcherServlet.properties': " + ex.getMessage());
    		}
    	}
    

    简单看下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
    
    #url映射
    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
    

    DispatcherServlet#onRefresh

    复写父类FrameworkServlet的onRefresh()方法,springmvc以此来完善相应的初始化操作,代码如下

    	//复写
    	@Override
    	protected void onRefresh(ApplicationContext context) {
    		initStrategies(context);
    	}
    

    直接看DispatcherServlet#initStrategies()初始化springmvc的策略对象,代码如下

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

    以上述程序的执行顺序,逐个分析

    DispatcherServlet#initMultipartResolver(ApplicationContext context)

    根据官方注释,此会去加载beanFactory的multipartResolverbean对象,适用于处理文件上传的操作,简单代码如下

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

    DispatcherServlet#initLocaleResolver(ApplicationContext context)

    本地校对解析,官方解释为获取id="localeResolver"的bean对象,如果没有则使用默认的org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver类创建bean对象

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

    Note:这里我们简单看下DispatcherServlet#getDefaultStrategy()的内部方法createDefaultStrategy()创建spring bean对象

    protected Object createDefaultStrategy(ApplicationContext context, Class<?> clazz) {
    //可通过ApplicationContext.getAutowireCapableBeanFactory()方法来额外的创建外部class为bean对象
    return context.getAutowireCapableBeanFactory().createBean(clazz);
    }

    DispatcherServlet#initThemeResolver(ApplicationContext context)

    DispatcherServlet#initLocaleResolver(ApplicationContext context),找寻id="themeResolver"的bean对象,没有则默认使用org.springframework.web.servlet.theme.FixedThemeResolver作为bean对象

    DispatcherServlet#initHandlerMappings(ApplicationContext context)

    初始化对资源访问的映射处理类,代码如下

    private void initHandlerMappings(ApplicationContext context) {
    		this.handlerMappings = null;
    		/***默认为true,表示从beanFactory和其父类获取所有的HandlerMapping
    		** beans
    		**<init-param>
    		* <param-name>detectAllHandlerMappings</param-name>
    		* <param-value>true/false</param-value>
    		*/
    		if (this.detectAllHandlerMappings) {
    			//从祖先类到子类都去找寻相应的资源
    			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 {
    				//否则获取本springmvc的上下文中的单个`id="handlerMapping"`的HandlerMapping bean
    				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.
    			}
    		}
    
    		//如果detectAllHandlerMappings=false且springmvc不包含相应的`handlerMapping`bean 则取默认的HandlerMappings
    		if (this.handlerMappings == null) {
    			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
    			if (logger.isDebugEnabled()) {
    				logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
    			}
    		}
    	}
    

    默认的HandlerMappings为org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping,从字面上可知前者是根据beanName直接映射请求,后者是注解方式的映射请求

    DispatcherServlet#initHandlerAdapters(ApplicationContext context)

    此处类似DispatcherServlet#initHandlerMapping()

    1. detectAllHandlerAdapters默认为true,也可通过web.xml修改值,表示找寻所有满足HandlerAdapter.class的beans;若为false,则寻找springmvc本身上下文环境(springmvc配置文件)的id="handlerAdapter"的单个bean对象。所以不管如何,springmvc若指定了handlerAdapterbean,其总是会被加载

    2. 默认的策略对象为SimpleControllerHandlerAdapter-简单的Controller请求处理

    DispatcherServlet#initHandlerExceptionResolvers(ApplicationContext context)

    此处类似DispatcherServlet#initHandlerMapping()

    1. detectAllHandlerExceptionResolvers默认为true,也可通过web.xml修改值,表示找寻所有满足HandlerExceptionResolver.class的beans;若为false,则寻找springmvc本身上下文环境(springmvc配置文件)的id="handlerExceptionResolver"的单个bean对象。所以不管如何,springmvc若指定了handlerExceptionResolverbean,其总是会被加载

    2. 默认的策略对象为SimpleControllerHandlerAdapter-简单的Controller请求处理

    DispatcherServlet#initRequestToViewNameTranslator(ApplicationContext context)

    此处同DispatcherServlet#initLocaleResolver()方法

    1. 首先找寻springmvc上下文中的id="viewNameTranslator"的bean,类型为RequestToViewNameTranslator.class
    2. 不然则采用默认的策略对象org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator-对请求的URI直接映射到view对象

    DispatcherServlet#initViewResolvers(ApplicationContext context)

    此处类似DispatcherServlet#initViewResolvers()

    1. detectAllViewResolvers默认为true,也可通过web.xml修改值,表示找寻所有满足ViewResolver.class的beans;若为false,则寻找springmvc本身上下文环境(springmvc配置文件)的id="viewResolver"的单个bean对象。所以不管如何,springmvc若指定了viewResolverbean,其总是会被加载

    2. 默认的策略对象为InternalResourceViewResolver-默认解析为jsp视图

    DispatcherServlet#initFlashMapManager(ApplicationContext context)

    此处同DispatcherServlet#initLocaleResolver()方法

    1. 首先找寻springmvc上下文中的id="flashMapManager"的bean,类型为FlashMapManager.class
    2. 不然则采用默认的策略对象org.springframework.web.servlet.support.SessionFlashMapManager-保存并检索FlashMap属性

    小结

    本文只介绍springmvc额外的初始化操作,包括文件上传处理类、请求映射处理类/适配器、异常处理类、视图解析类等等

  • 相关阅读:
    Jq操作表格
    最新web 2.0 配色 (一)
    Jqtable edit
    Jq公告渐隐弹出
    Jq模拟最大化最小化关闭
    JqtoggleClass
    Jq弹出公告
    jquery左右拉效果
    最新web 2.0 配色 (二)
    ZenCoding各个工具安装
  • 原文地址:https://www.cnblogs.com/question-sky/p/6925681.html
Copyright © 2020-2023  润新知