SpringBoot 自动配置的web组件

1,版本

2.0.2.RELEASE

2,查阅官网

①,在27.1章节已有详细说明

②,翻译

以下是SpringBoot对SpringMVC的默认配置:(WebMvcAutoConfiguration)
Inclusion of  ContentNegotiatingViewResolver and  BeanNameViewResolver beans.
自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何
渲染(转发?重定向?))
ContentNegotiatingViewResolver:组合所有的视图解析器的;

如何定制:我们可以自己给容器中添加一个视图解析器;自动的将其组合进来;
Support for serving static resources, including support for WebJars (see below).静态资源文件夹路
径,webjars
Static  index.html support. 静态首页访问
Custom  Favicon support (see below). favicon.ico
自动注册了 of  Converter ,  GenericConverter ,  Formatter beans.
Converter:转换器; public String hello(User user):类型转换使用Converter
Formatter 格式化器; 2017.12.17===Date;

自己添加的格式化器转换器,我们只需要放在容器中即可
Support for  HttpMessageConverters (see below).
HttpMessageConverter:SpringMVC用来转换Http请求和响应的;User---Json;
HttpMessageConverters 是从容器中确定;获取所有的HttpMessageConverter;
自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中
(@Bean,@Component)
Automatic registration of  MessageCodesResolver (see below).定义错误代码生成规则
Automatic use of a  ConfigurableWebBindingInitializer bean (see below).
我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添

③,locale解析类

        @Bean
        @ConditionalOnMissingBean
		@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
		public LocaleResolver localeResolver() {
			if (this.mvcProperties
					.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
				return new FixedLocaleResolver(this.mvcProperties.getLocale());
			}
            //默认用这个做本地化解析
			AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
			localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
			return localeResolver;
		}	

    @Override
	public Locale resolveLocale(HttpServletRequest request) {
		Locale defaultLocale = getDefaultLocale();
        //在使用本地化的时候是根据浏览器的语言决定用那种本地化的
		if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
			return defaultLocale;
		}
    }

④,错误响应消息格式

       //消息显示格式
       @Override
		public MessageCodesResolver getMessageCodesResolver() {
			if (this.mvcProperties.getMessageCodesResolverFormat() != null) {
				DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();
				resolver.setMessageCodeFormatter(
						this.mvcProperties.getMessageCodesResolverFormat());
				return resolver;
			}
			return null;
		}

    //messageCodesResolverFormat 是Format 类型
    private DefaultMessageCodesResolver.Format messageCodesResolverFormat;

    //而Format 实际上是一个enum
     public enum Format implements MessageCodeFormatter {

		/**
		 * 错误码,对象名,字段
		 * {@code errorCode + "." + object name + "." + field}
		 */
		PREFIX_ERROR_CODE {
			@Override
			public String format(String errorCode, @Nullable String objectName, @Nullable String field) {
				return toDelimitedString(errorCode, objectName, field);
			}
		},

⑤,添加转换器和格式化器

@Override
		public void addFormatters(FormatterRegistry registry) {
            //从容器中获取转换器
			for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
				registry.addConverter(converter);
			}
			for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
				registry.addConverter(converter);
			}
           //从容器中获取格式化器
			for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
				registry.addFormatter(formatter);
			}
		}

//也就是说如果我们想自定义,只需要给容器加入对应的格式化器和转换器即可,springboot会自动让我们配置的优先生效

⑥,视图解析器

        //默认视图解析器为ContentNegotiatingViewResolver ,会从容器中拿到所有的视图解析器
        //如果能对应视图解析器解析就返回解析结果
        //我们自定义的是视图解析器只要加入容器就会生效
        @Bean
		@ConditionalOnBean(ViewResolver.class)
		@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)		
        public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
			ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
			resolver.setContentNegotiationManager(
					beanFactory.getBean(ContentNegotiationManager.class));
			// ContentNegotiatingViewResolver uses all the other view resolvers to locate
			// a view so it should have a high precedence
			resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
			return resolver;
		}

⑦,ConfigurableWebBindingInitializer 

        //先从容器中获取,获取不到就利用父类获取 
        @Override
		protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
			try {
				return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
			}
			catch (NoSuchBeanDefinitionException ex) {
				return super.getConfigurableWebBindingInitializer();
			}
		}

        //父类就new 一个ConfigurableWebBindingInitializer 
        protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
		ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();

        //主要方法
    @Override
	public void initBinder(WebDataBinder binder) {
		binder.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
		if (this.directFieldAccess) {
			binder.initDirectFieldAccess();
		}
		if (this.messageCodesResolver != null) {
			binder.setMessageCodesResolver(this.messageCodesResolver);
		}
		if (this.bindingErrorProcessor != null) {
			binder.setBindingErrorProcessor(this.bindingErrorProcessor);
		}
		if (this.validator != null && binder.getTarget() != null &&
				this.validator.supports(binder.getTarget().getClass())) {
			binder.setValidator(this.validator);
		}
		if (this.conversionService != null) {
			binder.setConversionService(this.conversionService);
		}
		if (this.propertyEditorRegistrars != null) {
			for (PropertyEditorRegistrar propertyEditorRegistrar : this.propertyEditorRegistrars) {
				propertyEditorRegistrar.registerCustomEditors(binder);
			}
		}
	}

⑧,对静态路径的映射

//这个就是对资源的映射
public void addResourceHandlers(ResourceHandlerRegistry registry) {
			if (!this.resourceProperties.isAddMappings()) {
				logger.debug("Default resource handling disabled");
				return;
			}
			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			CacheControl cacheControl = this.resourceProperties.getCache()
					.getCachecontrol().toHttpCacheControl();
			if (!registry.hasMappingForPattern("/webjars/**")) {
                //将/webjars/** 都定位到classpath:/META-INF/resources/webjars/
				customizeResourceHandlerRegistration(registry
						.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/")
						.setCachePeriod(getSeconds(cachePeriod))
						.setCacheControl(cacheControl));
			}
            //staticPathPattern  默认是 /** ,即所有请求
			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
				customizeResourceHandlerRegistration(
						registry.addResourceHandler(staticPathPattern)
                                //这些路径我们也叫静态资源路径,只要没人处理就定位到此处
								.addResourceLocations(getResourceLocations(
										this.resourceProperties.getStaticLocations()))
								.setCachePeriod(getSeconds(cachePeriod))
								.setCacheControl(cacheControl));
			}
		}

⑨,对欢迎页的映射

	public WelcomePageHandlerMapping welcomePageHandlerMapping(
				ApplicationContext applicationContext) {
			return new WelcomePageHandlerMapping(
					new TemplateAvailabilityProviders(applicationContext),
					applicationContext, getWelcomePage(),//所有的静态资源文件夹下的index.html
					this.mvcProperties.getStaticPathPattern());//被 /** 映射
		}

10,对favicon.ico 的映射

public SimpleUrlHandlerMapping faviconHandlerMapping() {
				SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
				mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
                //将任意路径的favicon.ico 映射到静态资源文件夹下
				mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
						faviconRequestHandler()));
				return mapping;
			}

猜你喜欢

转载自my.oschina.net/u/3574106/blog/1820871
今日推荐