1、Spring Boot 的自动配置

  Spring Boot 为 Spring MVC 提供了自动配置,适用于大多数应用程序。首先查看官方文档,看看 SpringBoot 对 Spring MVC 做了哪些配置。(官网)

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

  1. 包含 ContentNegotiatingViewResolver 和 BeanNameViewResolver beans。
    • 自动配置了 ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发或重定向))。
    • ContentNegotiatingViewResolver:组合所有的视图解析器的;
    • 我们可以自己给容器中添加一个视图解析器;自动的将其组合进来。
  2. 支持提供静态资源,包括对 WebJars 的支持。
  3. 自动注册 Converter , GenericConverter 和 Formatter beans。
    • Converter:转换器; public String hello(User user) 和 JSON 类型转换使用 Converter。
    • Formatter 格式化器; 2017.12.17 转换为 Date;
    • 自己添加的格式化器转换器,我们只需要放在容器中即可。
  4. 支持 HttpMessageConverters
    • HttpMessageConverter:Spring MVC 使用该 HttpMessageConverter 接口转换 HTTP 请求和响应;User—JSON;
    • HttpMessageConverters 是从容器中确定;获取所有的 HttpMessageConverter 实现类;
    • 自己给容器中添加 HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)
  5. 自动注册 MessageCodesResolver 。
    • MessageCodesResolver 定义渲染错误消息的策略
  6. 静态 index.html 支持
  7. 自定义 Favicon 支持
  8. 自动使用 ConfigurableWebBindingInitializer bean
    • Spring MVC 使用 WebBindingInitializer 来初始化 WebDataBinder 特定请求。
    • 可以配置一个 ConfigurableWebBindingInitializer 来替换默认的;(添加到容器)

  如果你想保留 Spring Boot MVC 功能,并且你想添加额外的 MVC 配置(拦截器,格式化程序,视图控制器和其他功能),你可以添加自己的@Configuration 类(WebMvcConfigurer ),但不能添加 @EnableWebMvc 。如果您希望提供 RequestMappingHandlerMapping , RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 的自定义实例,则可以声明 WebMvcRegistrationsAdapter 实例以提供此类组件。
  如果您想完全控制 Spring MVC,可以添加自己的@Configuration 注释@EnableWebMvc 。

SpringBoot 对静态资源的映射规则

  在 ResourceProperties 配置文件类中,可以看到静态资源的位置。

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {

	private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

	/**
	 * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
	 * /resources/, /static/, /public/].
	 */
	private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;

  Spring MVC 的配置 WebMvcAutoConfiguration 类中 addResourceHandlers 方法添加资源映射,所有 /webjars/**,都去 classpath:/META-INF/resources/webjars/ 找资源。

		@Override
		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/**")) {
				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));
			}

/** 访问当前项目的任何资源,都去(静态资源的文件夹)找映射。例如:访问 localhost:8080/zyx 等于去静态资源文件夹里面找 zyx。静态资源文件夹如下:

  • "classpath:/META-INF/resources/",
  • "classpath:/resources/",
  • "classpath:/static/",
  • "classpath:/public/
  • "/": 当前项目的根路径
什么是 WebJars

  WebJars 是被打包成 JAR 文件 (Java Archive)形式的客户端 Web 资源库(例如:jQuery、Bootstrap 等)。官网

  例如导入一个 jquery

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.4.1</version>
        </dependency>

  访问路径为:http://localhost:8080/webjars/jquery/3.4.1/jquery.js;目录结构为:

image.png

2、扩展 Spring MVC

  编写一个配置类(@Configuration),是 WebMvcConfigurer 类型;不能标注@EnableWebMvc

视图映射功能

  浏览器发送请求,SpringBoot 实现请求到相应页面,并且通过模板引擎解析。

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry){
        // 浏览器发送 /aaa 请求到success
        registry.addViewController("/aaa").setViewName("success");
    }
}

原理

  WebMvcAutoConfiguration 是 SpringMVC 的自动配置类。在 WebMvcAutoConfiguration 中有个内部类 WebMvcAutoConfigurationAdapter 实现了 WebMvcConfigurer 并导入了 EnableWebMvcConfiguration 组件。

	@Configuration(proxyBeanMethods = false)
	@Import(EnableWebMvcConfiguration.class)
	@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
	@Order(0)
	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {

  EnableWebMvcConfiguration 组件继承了 DelegatingWebMvcConfiguration 类。

	@Configuration(proxyBeanMethods = false)
	public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {

  DelegatingWebMvcConfiguration 类中有个方法,获取容器中所有的 WebMvcConfigurer 添加到 WebMvcConfigurerComposite 类中。

	private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

	@Autowired(required = false)
	public void setConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.configurers.addWebMvcConfigurers(configurers);
		}
	}

  在 WebMvcConfigurerComposite 类中获取所有配置,都是将所有的 WebMvcConfigurer 实现类的配置综合到一起。所以扩展 Spring MVC 只需实现 WebMvcConfigurer 接口即可。

	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		for (WebMvcConfigurer delegate : this.delegates) {
			delegate.addViewControllers(registry);
		}
	}

3、全面接管 Spring MVC

  我们在配置类中添加 @EnableWebMvc 注解,可以让 SpringBoot 对 SpringMVC 做的所有配置都失效。

原理

  @EnableWebMvc 注解添加了 DelegatingWebMvcConfiguration 组件

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

  而 DelegatingWebMvcConfiguration 继承 WebMvcConfigurationSupport

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

  在 WebMvcAutoConfiguration 类中有 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) ,作用:如果容器中有 WebMvcConfigurationSupportWebMvcAutoConfiguration 不生效。所以 SpringBoot 对 SpringMVC 做的所有配置就都失效。

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

  @EnableWebMvcWebMvcConfigurationSupport 组件导入进来,导入的 WebMvcConfigurationSupport 只是 SpringMVC 最基本的功能;

4、修改 SpringBoot 的默认配置

  1. SpringBoot 在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;
  2. 在 SpringBoot 中会有很多的 xxxConfigurer 帮助我们进行扩展配置。
  3. 在 SpringBoot 中会有很多的 xxxCustomizer 帮助我们进行定制配置。

标题:SpringBoot 配置之 SpringMVC 自动配置
作者:Yi-Xing
地址:http://47.94.239.232/articles/2020/07/18/1595043715770.html
博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!