zoukankan      html  css  js  c++  java
  • SpringBoot源码学习系列之SpringMVC自动配置

    源码学习系列之WebMvc自动配置原理笔记

    @

    web的自动配置在SpringBoot项目中是一个很重要的方面,实现代码在spring-boot-autoconfigure工程里:
    在这里插入图片描述
    按照官方文档的说法,SpringBoot官方的说法,Springboot的SpringMVC自动配置,主要提供了如下自动配置:
    在这里插入图片描述

    WebMvcAutoConfiguration.java这个类很关键,这个就是SpringBoot Springmvc自动配置的一个很关键的配置类

    @Configuration(proxyBeanMethods = false)//指定WebMvcAutoConfiguration不代理方法
    @ConditionalOnWebApplication(type = Type.SERVLET)//在web环境(selvlet)才会起效
    @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })//系统有有Servlet,DispatcherServlet(Spring核心的分发器),WebMvcConfigurer的情况,这个自动配置类才起效
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)//系统没有WebMvcConfigurationSupport这个类的情况,自动配置起效
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
    @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
    		ValidationAutoConfiguration.class })
    public class WebMvcAutoConfiguration {
    ....
    }
    

    翻下源码,可以看到WebMvcAutoConfiguration自动配置类里还有一个WebMvcConfigurer类型的配置类,2.2.1版本是implements WebMvcConfigurer接口,1.+版本是extends WebMvcConfigurerAdapter
    在这里插入图片描述

    @Configuration(proxyBeanMethods = false)//定义为配置类
    	@Import(EnableWebMvcConfiguration.class)//spring底层注解,将EnableWebMvcConfiguration加到容器
    	@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })//使WebMvcProperties、ResourceProperties配置类生效
    	@Order(0)
    	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    	....
    }
    

    1、ContentNegotiatingViewResolver

    在这里插入图片描述
    如图,是视图解析器的自动配置,这个类起效的情况是系统没有ContentNegotiatingViewResolver类的情况,就调用改方法自动创建ContentNegotiatingViewResolver类
    在这里插入图片描述
    关键的是ContentNegotiatingViewResolver类,翻下ContentNegotiatingViewResolver类,找到如下重要的初始化方法

    @Override
    	protected void initServletContext(ServletContext servletContext) {
    	//调用Spring的BeanFactoryUtils扫描容器里的所有视图解析器ViewResolver类
    		Collection<ViewResolver> matchingBeans =
    				BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values();
    		if (this.viewResolvers == null) {
    			this.viewResolvers = new ArrayList<>(matchingBeans.size());
    			//遍历候选的viewResolvers,封装到this.viewResolvers列表
    			for (ViewResolver viewResolver : matchingBeans) {
    				if (this != viewResolver) {
    					this.viewResolvers.add(viewResolver);
    				}
    			}
    		}
    		else {
    			for (int i = 0; i < this.viewResolvers.size(); i++) {
    				ViewResolver vr = this.viewResolvers.get(i);
    				if (matchingBeans.contains(vr)) {
    					continue;
    				}
    				String name = vr.getClass().getName() + i;
    				obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(vr, name);
    			}
    
    		}
    		AnnotationAwareOrderComparator.sort(this.viewResolvers);
    		this.cnmFactoryBean.setServletContext(servletContext);
    	}
    

    所以ContentNegotiatingViewResolver类的作用就是组合所有的视图解析器,自动配置了ViewResolver(视图解析器作用,根据方法返回值得到视图对象view)

    往下翻代码,可以看到resolveViewName方法,里面代码是从this.viewResolvers获取候选的视图解析器,遍历容器里所有视图,然后通过如图所标记的获取候选视图的方法,获取候选的视图列表,再通过getBestView获取最合适的视图
    在这里插入图片描述
    遍历所有的视图解析器对象,从视图解析器里获取候选的视图,封装成list保存
    在这里插入图片描述
    ok,跟了源码就是只要将视图解析器丢到Spring容器里,就可以加载到

    写个简单的视图解析类
    在这里插入图片描述
    DispatcherServlet是Spring核心分发器,找到doDispatch方法,debug,可以看到加的视图解析器加载到了
    在这里插入图片描述

    2、静态资源

    也就是官方说的,如下图所示:
    在这里插入图片描述
    翻译过来就是支持静态资源包括webjars的自动配置,webjars,就是以maven等等方式打成jar包的静态资源,可以去webjars官网看看文档:

    使用的话,直接去webjars官网负责对应的配置,加到项目里就可以
    在这里插入图片描述
    路径都是在META-INF/webjars/**

    WebMvcAutoConfiguration.addResourceHandlers,这个是比较重要的资源配置方法

    @Override
    		public void addResourceHandlers(ResourceHandlerRegistry registry) {
    			if (!this.resourceProperties.isAddMappings()) {
    				logger.debug("Default resource handling disabled");
    				return;
    			}
    			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
    			//CacheControl是Spring框架提供的http缓存
    			CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
    			//读取到webjars资源,将classpath:/META-INF/resources/webjars/的webjars资源都扫描出来
    			if (!registry.hasMappingForPattern("/webjars/**")) {
    				customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
    						.addResourceLocations("classpath:/META-INF/resources/webjars/")
    						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    			}
    			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    			if (!registry.hasMappingForPattern(staticPathPattern)) {
    				customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
    						.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
    						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    			}
    		}
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    ok,通过源码可以知道,Springboot支持webjars和其它等等静态资源,其它的静态资源要放在如下目录里,Springboot就能自动加载到

    • classpath:/META-INF/resources/
    • classpath:/resources/
    • classpath:/static/
    • classpath:/public/
    • classpath:/

    3、自动注册 Converter, GenericConverter, and Formatter beans.

    在这里插入图片描述
    翻译过来就是自动注册了 Converter, GenericConverter, and Formatter beans.

    • Converter:转换器 ,作用就是能自动进行类型转换
      eg: public String hello(User user),这是一个方法,然后前端视图传来的参数通过转换器能够根据属性进行映射,然后进行属性类型转换
    • Formatter :格式化器,eg:比如对前端传来的日期2019/11/25,进行格式化处理

    源码在这里,WebMvcAutoConfiguration.addFormatters方法是添加格式化器的方法
    在这里插入图片描述
    同理,也是从Spring容器里将这几种类拿过来
    在这里插入图片描述

    当然,还有其它的,比如WebMvcAutoConfiguration.localeResolver方法是实现i18n国际化语言支持的自动配置

    @Bean
    		@ConditionalOnMissingBean//没有自定义localeResolver的情况
    		@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")//application.properties有配置了spring.mvc.locale
    		public LocaleResolver localeResolver() {
    			if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
    				return new FixedLocaleResolver(this.mvcProperties.getLocale());
    			}
    			//默认使用AcceptHeaderLocaleResolver 
    			AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
    			localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
    			return localeResolver;
    		}
    

    具体的源码参考我之前博客:SpringBoot系列之i18n国际化多语言支持教程,博客里面有涉及源码的

    4、支持HttpMessageConverters

    HttpMessageConverters :消息转换器,Springmvc中用来转换http请求和响应的

    源码里是通过configureMessageConverters方法实现,很显然也是从容器里获取的
    在这里插入图片描述

    在这里插入图片描述
    官方文档里也进行了比较详细描述,Springboot已经为我们自动配置了json的、xml的自动转换器,当然你也可以自己添加
    在这里插入图片描述

    5、支持MessageCodesResolver

    在这里插入图片描述
    MessageCodesResolver:是消息解析器,WebMvcAutoConfiguration.getMessageCodesResolver是实现Exception异常信息格式的
    在这里插入图片描述
    WebMvcProperties配置文件定义的一个异常枚举值
    在这里插入图片描述

    在这里插入图片描述
    格式为如图所示,定了了错误代码是生成规则:
    在这里插入图片描述

    6、首页支持

    在这里插入图片描述
    Springboot默认的首页是index.html,也就是你在classpath路径丢个index.html文件,就被Springboot默认为首页,或者说欢迎页

    如图示代码,就是遍历静态资源文件,然后获取index.html作为欢迎页面

    在这里插入图片描述

    7、网站logo设置

    在这里插入图片描述
    Springboot1.+版本,是有默认的logo图标的,2.2.1版本,经过全局搜索,没有发现给自定义的图标,使用的话,是直接丢在classpath路径,文件命名为favicon.ico,不过在2.2.1代码并没有找到相应的配置代码,1.+版本是有的,不过文档还是有描述了

    8、ConfigurableWebBindingInitializer 初始绑定器

    在这里插入图片描述
    跟下源码,也是从Spring容器里获取的,然后注意到,如果没有这个ConfigurableWebBindingInitializer ,代码就会调用基类的getConfigurableWebBindingInitializer
    在这里插入图片描述
    源码,这里也是创建一个getConfigurableWebBindingInitializer
    在这里插入图片描述

    ConfigurableWebBindingInitializer 是Springboot为系统自动配置的,当然我们也可以自己定义一个ConfigurableWebBindingInitializer ,然后加载到容器里即可

    初始化绑定的方法,ok,本博客简单跟一下源码
    在这里插入图片描述

    注意:
    ok,Springboot官方文档里还有这样的描述,如图所示
    在这里插入图片描述
    意思是,在使用webmvcConfigurer配置的时候,不要使用@EnableWebMvc注解,为什么不要使用呢?因为使用了@EnableWebMvc,就是实现全面接管SpringMVC自动配置,也就是说其它的自动配置都会失效,全部自己配置

    原理是为什么?可以简单跟一下源码,如图,SpringMVC自动配置类,有这个很关键的注解,这个注解的意思是@WebMvcConfigurationSupport注解不在系统时候自动配置才起效

    在这里插入图片描述
    然后为什么加了@EnableWebMvc自动配置就可以被全面接管?点一下@EnableWebMvc源码

    在这里插入图片描述
    很显然,DelegatingWebMvcConfiguration类extends WebMvcConfigurationSupport类,所以这也就是为什么@EnableWebMvc注解能实现全面接管自动配置的原理在这里插入图片描述

  • 相关阅读:
    c# 简单的通用基础字典
    c#中设置像数量,价格,金额等的textbox的限制条件,用户只能输入数字或小数
    Introduction to Project Management(I)
    MoSCoW Method
    A Guide to Creating a Quality Project Schedule
    Estimating Project Costs
    SMART Goals
    10 Ways to Inspire Your Team
    ExtractTablesFromSQL
    iOS-传感器及使用
  • 原文地址:https://www.cnblogs.com/mzq123/p/11936054.html
Copyright © 2011-2022 走看看