SpringBoot(四) Web开发(1):SpringBoot关于静态资源的映射、Thymeleaf了解和SpringMVC的自动配置

1、简介

SpringBoot就是为了来简化和快速开发我们的项目的,所以使用SpringBoot是很简单的,只需要简单的几步就好了;如果要使用SpringBoot进行Web开发,那我们需要选中web模块,SpringBoot便会帮我们做好Web开发相关的自动配置,我们只要写业务代码就行了。
1)、创建SpringBoot应用,选中我们需要的模块;
2)、SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来;
3)、自己编写业务代码;

所以使用SpringBoot是很简单的,但是如果想要知其所以然,就需要知道SpringBoot的自动配置原理,然后才能游刃有余。有两个最基本的地方,那就是SpringBoot里面有大量的类似:xxxxAutoConfiguration:用来帮我们给容器中自动配置组件;
一个xxxxAutoConfiguration就会对应一个 xxxxProperties 配置类,用来封装配置文件的内容;我们可以在application.properties配置文件中进行自定义的配置。

创建新的工程spring-boot-04-web,创建方式和之前是一样的,pom.ml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zdw.springboot</groupId>
    <artifactId>spring-boot-04-web-restful</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-04-web-restful</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--引入jquery-webjar-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.3.1</version>
        </dependency>

        <!--引入bootstrap-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

SpringBoot的版本是2.2.5

2、SpringBoot对静态资源的映射规则

在以前的Web开发中,我们的项目都是以war为打包方式的,创建的工程中也会有webapp等目录,里面是进行web开发相关的静态资源和相关的视图组件。但是在SpringBoot中,基本上都是 jar 打包方式,那么它也能支持这些静态资源和视图吗?
下面我们通过查看WebMvcAutoConfiguration 来查看SpringBoot对静态资源的映射规则:

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {

    //静态资源映射规则的方法
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
                //所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找资源
                CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
                if (!registry.hasMappingForPattern("/webjars/**")) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations
(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                //"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations
   (WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
    }

    //欢迎页面的映射
    @Bean
    public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
            WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
            welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
            return welcomePageHandlerMapping;
    }

}

ResourceProperties 类的部分代码:(WebMvcAutoConfiguration 中很多时候都是要到这个方法里面找路径的)

@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
    private String[] staticLocations;
    private boolean addMappings;
    private final ResourceProperties.Chain chain;
    private final ResourceProperties.Cache cache;

    public ResourceProperties() {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
        this.addMappings = true;
        this.chain = new ResourceProperties.Chain();
        this.cache = new ResourceProperties.Cache();
    }

    public String[] getStaticLocations() {
        return this.staticLocations;
    }
}

2.1 第三方jar包中的静态资源的访问

当我们要访问引入到项目中的jar包里面的js,css等静态资源的时候,该怎么去访问呢?
从上面的源码可以分析出,SpringBoot对jar包中的静态资源是遵守下面这样的规则:
1、所有请求路径为: /webjars/** (就是以webjars开头的所有路径),都会去 jar包的类路径下classpath下面的/META-INF/resources/webjars/ 找资源;webjars:作用就是:以jar包的方式引入静态资源;官网地址:https://www.webjars.org

<!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可 -->
<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.3.1</version>
</dependency>

例如:我们的项目中引入jquery的webjars依赖,如下:
在这里插入图片描述
那么我们如何可以访问到里面的jquery.js文件的内容呢?

启动项目,在浏览器上访问:http://localhost:8080/webjars/jquery/3.3.1/jquery.js 在浏览器上就可以看到对应的内容了,

2.2 自定义的静态资源的映射规则

2.1 讲的是以jar包的方式引入的静态资源,SpringBoot是如何去映射的。那么我们在项目中自定义的一些静态资源,SpringBoot的映射规则又是怎样的呢?

  从上面的源码可以知道,SpringBoot会从下面几个路径找静态资源:

         "classpath:/META‐INF/resources/",
         "classpath:/resources/",
         "classpath:/static/",
         "classpath:/public/"
         "/":当前项目的根路径

对应我们项目中的结构图(这些文件夹都可以手动创建,使用Spring Initializer 方式创建是SpringBoot项目,会自动帮我们在类路径的根目录resources下面 创建一个 static的静态资源目录):
在这里插入图片描述
例如,我们在resources静态资源目录下面,放置了我们的静态资源(如上图所示,分别放置了a.png c.jpg b.jpg d.png),启动工程之后,我们可以在浏览器访问:http://localhost:8080/a.png http://localhost:8080/b.jpg http://localhost:8080/c.jpg http://localhost:8080/d.png 就都能访问到对应的静态资源:

在这里插入图片描述
当然,也可以在配置文件application.properties中指定映射静态资源的位置,配置了之后,默认的几个位置的静态资源就访问不到了,比如在application.properties中配置:

spring.resources.static-locations=classpath:/hello/

此时,上面所有的访问地址,都无法访问到静态资源。
所以如果我们要添加自己的静态资源文件夹,在配置的时候,应该保证默认的配置不要动,只是在后面加上自己的文件夹配置:

spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resoures/,classpath:/static/,classpath:/public/,classpath:/hello/

2.3 欢迎页的默认配置

SpringBoot默认也会从下面的路径去找index.html,作为欢迎页面,它被 “/**” 映射:也就是说请求任何的路径都会从:

静态资源文件夹下的所有index.html页面;被**"/"**映射;

         "classpath:/META‐INF/resources/",
         "classpath:/resources/",
         "classpath:/static/",
         "classpath:/public/"

下面找index.html,所以我们可以在这四个路径的任何一个下面编写index.html,都能被SpringBoot访问到。

3、Thymeleaf模板引擎

**SpringBoot使用内嵌的tomcat作为web容器,默认是不支持jsp的。jsp就是一种模板引擎,它的好处就是可以使用c:if c:foreach等进行数据的操作。市面上的模板引擎有:JSP、Freemarker、Velocity、Thymeleaf等。他们的原理都是差不多的,模板引擎可以把模板和数据进行对应的渲染,然后进行输出。

3.1 引入Thymeleat

SpringBoot推荐使用的模板引擎是Thymeleaf,需要导入Thymeleaf的坐标:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

3.2 Thymeleaf的使用

Themeleaf的自动配置规则,主要可以看:ThymeleafProperties

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");

	private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";

可以看出:只要我们把HTML页面放在classpath:/templates/,thymeleaf就能自动渲染;

3.2.1 导入thymeleaf的名称空间

要想使用thymeleaf的语法有提示,就应该在html中导入名称空间:

<html lang="en" xmlns:th="http://www.thymeleaf.org">

3.2.2 thymeleaf语法

示例:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>成功!</h1>
    <!--th:text 将div里面的文本内容设置为${hello}获取的值 -->
    <div th:text="${hello}">这是显示欢迎信息</div>
</body>
</html>

3.2.3 语法规则

1、th:text:改变当前元素里面的文本内容;
th:可以和任意html属性一起使用;来替换原生属性的值。常用的如下:
在这里插入图片描述
2、表达式
Variable Expressions : ${…}:获取变量值;OGNL;
1)、获取对象的属性、调用方法
2)、使用内置的基本对象:

#ctx : the context object.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object.
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object.
#servletContext : (only in Web Contexts) the ServletContext object.

3)、使用内置的一些工具对象:

#execInfo : information about the template being processed.
#messages : methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{} syntax.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
#ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).

** {…}:选择表达式:和${}在功能上是一样*

选择表达式:和 $ {}在功能上是一样;
补充:配合 th:object="${session.user}:

<div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
    <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>

#{…}:获取国际化内容

@{…}:定义URL

@{/order/process(execId=${execId},execType='FAST')}

~{…}:片段引用表达式

<div th:insert="~{commons :: main}">...</div>

Literals(字面量)

Text literals: 'one text' , 'Another one!' ,
Number literals: 0 , 34 , 3.0 , 12.3 ,
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,

Text operations:(文本操作)

String concatenation: +
Literal substitutions: |The name is ${name}|

Arithmetic operations:(数学运算)

Binary operators: + , - , * , / , %
Minus sign (unary operator): -

Boolean operations:(布尔运算)

Binary operators: and , or
Boolean negation (unary operator): ! , not

Comparisons and equality:(比较运算)

Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )

Conditional operators:条件运算(三元运算符)

If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)

Special tokens

No-Operation: _ 

4、SpringMVC自动配置

点击查看1.5.10.RELEASE官方文档
点击查看2.2.5.RELEASE官方文档

4.1 SpringBoot对SpringMVC的配置精髓

Spring MVC 自动配置:
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(SpringBoot提供了SpringMVC的大多数场景下的自动配置功能);

The auto-configuration adds the following features on top of Spring’s defaults(以下是SpringBoot对SpringMVC的默认配置):

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

    • 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
    • ContentNegotiatingViewResolver:视图解析器是可以配置多个的,他就是用来组合所有的视图解析器的;
    • 如何定制:我们可以自己给容器中添加一个视图解析器;自动的将其组合进来;
  • Support for serving static resources, including support for WebJars (covered later in this document)). 支持静态资源,包括支持webjars

  • Automatic registration of Converter, GenericConverter, and Formatter beans:自动注册了 of Converter, GenericConverter, Formatter beans.

    • Converter:转换器; public String hello(User user):类型转换使用Converter
    • Formatter 格式化器; 2017.12.17===Date;
@Bean
@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")//在文件中配置日期格式化的规则
public Formatter<Date> dateFormatter() {
	return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
}

自己添加的格式化器转换器,我们只需要放在容器中即可,SpringBoot会自动扫描并注册

  • Support for HttpMessageConverters (covered later in this document).

    • HttpMessageConverter:SpringMVC用来转换Http请求和响应的;User—Json;
    • HttpMessageConverters 是从容器中确定;获取所有的HttpMessageConverter;
      自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)
  • Automatic registration of MessageCodesResolver (covered later in this document). 定义错误代码生成规则

  • Static index.html support. 欢迎页(首页 )index.html的支持

  • Custom Favicon support (covered later in this document). favicon.ico的支持

  • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document). 自动配置了 Web请求的数据绑定初始化器,就是用来把请求参数绑定到我们的方法形参上面的
    我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. (如果你想保留SpringBoot对SpringMVC的定制,并且还想自定义一些东西,比如:interceptors,formatters等),你可以编写一个用注解@Configuration修饰的WebMvcConfigurer类型的类,但是不能使用@EnableWebMvc修饰。

If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.
如果你想提供有关:RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver自定义的实例,并且要保持SpringBoot 的MVC定制,你可以声明一个 WebMvcRegistrations 类型的类,然后使用它去提供自定义相关的组件实例。

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.
如果你想完全接管SpringMVC,你可以在自己编写的@Configuration 修饰的配置类上加上 @EnableWebMvc注解,或者添加你自己的@Configuration注释的DelegatingWebMvcConfiguration,如@EnableWebMvc的Javadoc所述

4.2 扩展SpringMVC

在使用SpringMVC的时候,我们需要配置一些自己的视图映射,或者是一些自定义的拦截器,以前都是在xml配置文件中进行配置,比如:

<mvc:view-controller path="/hello" view-name="success"/>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/hello"/>
            <bean></bean>
        </mvc:interceptor>
    </mvc:interceptors>

但是,在SpringBoot中是用Java配置类来代替上面的配置内容:编写一个配置类(@Configuration),是WebMvcConfigurer(SpringBoot1.x的时候是WebMvcConfigurerAdapter类型;不能标注@EnableWebMvc,既保留了所有的自动配置,也能用我们扩展的配置;

package com.zdw.springboot.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 使用注解@Configuration表明这是一个配置类,可以来扩展我们自己有关SpringMVC 的配置
 * 添加配置只需要实现WebMvcConfigurer对应的方法即可
 */
@Configuration
public class MySpringMvcConfig implements WebMvcConfigurer {

    /**
     * 添加视图映射,相当于以前在applicationContext.xml中添加:
     * <mvc:view-controller path="/hello" view-name="success"/>
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //浏览器发送 /hello请求直接来到 templates下面的seccess.html页面
        registry.addViewController("/hello").setViewName("success");
    }
}

原理分析:

  • 1、首先我们知道,SpringBoot关于web的自动配置都在类:WebMvcAutoConfiguration
  • 2、在它里面有这样一个静态内部类:
@Configuration(
        proxyBeanMethods = false
    )
    public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
        private final ResourceProperties resourceProperties;

我们看它的父类:DelegatingWebMvcConfiguration

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

    public DelegatingWebMvcConfiguration() {
    }

    @Autowired(required = false)
    //从容器中获取所有的WebMvcConfigurer
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
        }
    }
    //一个参考实现;将所有的WebMvcConfigurer相关配置都来一起调用;
	protected void addViewControllers(ViewControllerRegistry registry) {
        this.configurers.addViewControllers(registry);
    }

从容器中获取所有的WebMvcConfigurer,所以我们自定义的WebMvcController类型的配置类也会被加载生效。
3、容器中所有的WebMvcConfigurer都会一起起作用;
4、我们的配置类也会被调用;

4.3 全面接管SpringMVC

如果你不想使用SpringBoot对SpringMVC的自动配置,所有的配置都是我们自己配置;那么就在我们上面配置类上添加==@EnableWebMvc==即可;

package com.zdw.springboot.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 使用注解@Configuration表明这是一个配置类,可以来扩展我们自己有关SpringMVC 的配置
 * 添加配置只需要实现WebMvcConfigurer对应的方法即可
 *
 * @EnableWebMvc : 该注解的使用会全面接管SpringBoot的SpringMVC的配置,这样的话默认的SpringMvc配置就失效了,
 * 比如:静态资源的配置就失效,按照之前的方式访问不了静态资源了
 */
@Configuration
@EnableWebMvc
public class MySpringMvcConfig implements WebMvcConfigurer {

    /**
     * 添加视图映射,相当于以前在applicationContext.xml中添加:
     * <mvc:view-controller path="/hello" view-name="success"/>
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //浏览器发送 /hello请求直接来到 templates下面的seccess.html页面
        registry.addViewController("/hello").setViewName("success");
    }
}

此时再访问之前的静态资源:http://localhost:8080/webjars/jquery/3.3.1/jquery.js 就会报404错误了。

原理:为什么@EnableWebMvc自动配置就失效了?

  • 1、@EnableWebMvc的核心
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
  • 2、再看它导入的组件:DelegatingWebMvcConfiguration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

发现它是 WebMvcConfigurationSupport 的子类。

  • 3、再次回看:WebMvcAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {

@ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) :我们看到这里,意思是只有当没有配置 WebMvcConfigurationSupport 类型的Bean的时候,SpringBoot才会帮我们自动配置WebMvcAutoConfigutarion。而@EnableWebMvc将WebMvcConfigurationSupport组件导入进来;导入的WebMvcConfigurationSupport只是SpringMVC最基本的功能;

5、如果修改SpringBoot的自动配置

模式:

  • 1、SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver),就会将用户配置的和自己默认的组合起来;

  • 2、在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置;

  • 3、在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值