​ 今天来学习下WebMvcAutoConfiguration的自动配置,Spring mvc在web开发过程中是被使用最多的,开发中的各种各样的请求都跟spring mvc有关,所以有必要研究下spring boot中的这个配置类。

通过访问官方说明文档可以看到以下内容:官网地址

Spring Boot为Spring MVC提供了自动配置

自动配置在Spring的默认值之上添加了以下功能

  • 包含 ContentNegotiatingViewResolverBeanNameViewResolver

    • 自动配置了ViewResolver(视图解析器:根据方法的返回值得到对应的视图对象(View),视图对象决定如何渲染(是转发 还是重定向))
    • ContentNegotiatingViewResolver :组合所有的试图解析器
    • 如何定制:我们可以自己给容器中添加一个视图解析器,即可自动完成
  • Support for serving static resources, including support for WebJars 静态资源文件夹路径和webjars.

  • Static index.html support. 静态首页

  • Custom Favicon support (详情). 支持自定义网页图标

  • 自动注册 Converter, GenericConverter, and Formatter beans.

    • Converter 转换器 public String hello(User user):数据传参后 接收类型转换使用Converter

    • Formattrt:格式化器

      1
      2
      3
      4
      5
      6
      @Bean
      @ConditionalOnProperty(prefix = "spring.mvc", name = "date‐format")//在文件中配置日期格
      式化的规则
      public Formatter<Date> dateFormatter() {
      return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
      }

      自己添加的格式化转换器 只需放入容器即可

  • Support for HttpMessageConverters (详情).

    • HttpMessageConverters 是从容器中确定;获取所有的HttpMessageConverter; 自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中 (@Bean,@Component)
  • Automatic registration of MessageCodesResolver (详情).

    • HttpMessageConverter:SpringMVC用来转换Http请求和响应的;User—Json;
  • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).

    如果只是想扩展mvc功能,那么只需添加自己的@Configuration class 类型为WebMvcConfigurer,但不是 @EnableWebMvc

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //使用WebMvcConfigurer可以来扩展SpringMVC的功能
    @Configuration
    public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    // super.addViewControllers(registry);
    //浏览器发送 /atguigu 请求来到 success
    registry.addViewController("/atguigu").setViewName("success");
    }
    }

    如果要完全控制 Spring MVC 可以添加自己的@Configuration 同时添加注解@EnableWebMvc

    不建议全面控制Spring MVC

    此外 还有一些静态资源的配置

    静态资源映射

    默认支持对webjars的路径映射和其他静态资源路径映射

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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();
    //如果未注册 /webjars/** 则执行
    if (!registry.hasMappingForPattern("/webjars/**")) {
    customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
    .addResourceLocations("classpath:/META-INF/resources/webjars/")
    .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    /** 静态资源路径
    String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
    "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
    */
    //默认静态资源路径映射
    String staticPathPattern = this.mvcProperties.getStaticPathPattern();
    if (!registry.hasMappingForPattern(staticPathPattern)) {
    customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
    .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
    .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
    }
    }

    默认首页配置

    spring boot 默认配置了对首页的支持,只需要在静态或模板引擎文件夹下放index.html或index文件即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @Bean
    public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
    FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    //然后看这个构造函数
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
    new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
    this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    return welcomePageHandlerMapping;
    }

    private Optional<Resource> getWelcomePage() {
    String[] locations = getResourceLocations(this.resourceProperties.getStaticLocations());
    return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
    }

    private Resource getIndexHtml(String location) {
    return this.resourceLoader.getResource(location + "index.html");
    }

    WelcomePageHandlerMapping 构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
    ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {
    //获取静态路径下的index.html
    if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
    logger.info("Adding welcome page: " + welcomePage.get());
    setRootViewName("forward:index.html");
    }
    //获取模板引擎下的index文件
    else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
    logger.info("Adding welcome page template: index");
    setRootViewName("index");
    }
    }