SpringBoot 自動配置的web組件

1,版本

2.0.2.RELEASEhtml

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;
			}
相關文章
相關標籤/搜索