Springboot MVC 自动配置
Springboot MVC 自动配置
官方文档阅读
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
The auto-configuration adds the following features on top of Spring’s defaults:
- Inclusion of
ContentNegotiatingViewResolver
andBeanNameViewResolver
beans. - Support for serving static resources, including support for WebJars (covered later in this document).
- Automatic registration of
Converter
,GenericConverter
, andFormatter
beans. - Support for
HttpMessageConverters
(covered later in this document). - Automatic registration of
MessageCodesResolver
(covered later in this document). - Static
index.html
support. - Automatic use of a
ConfigurableWebBindingInitializer
bean (covered later in this document).
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
.
如果您希望保留 Spring Boot MVC 定制并进行更多的 MVC 定制(拦截器、格式化程序、视图控制器和其他特性) ,可以添加您自己的 webmvcrer 类型的@Configuration 类,但不要添加@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.
如果你想提供自定义的 requestmappinghandler mapping、 requestmappinghandler adapter 或 exceptionhandlerexceptionmvc 定制,你可以声明一个类型为 WebMvcRegistrations 的 bean,并使用它来提供这些组件的自定义实例
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
.
如果你想完全控制 Spring MVC,你可以添加你自己的@Configuration 注释@EnableWebMvc,或者像在@EnableWebMvc 的 Javadoc 中描述的那样添加你自己的@Configuration 注释 delegatingwebmvcvc 配置。
个人解读
SpringBoot本身是为Spring MVC提供了自动配置,一般情况下是满足使用需求的。最近在学习的时候,需要使用矩阵变量,需要对springmvc的配置需要进行更改,遇到了一些疑问,通过源码探索了一下,今天在此总结,方便以后自己来看。
上面的官方文档中,最重要的两段话:
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
.(在自动配置的基础上,进行用户自定义配置)
如果您希望保留 Spring Boot MVC 定制并进行更多的 MVC 定制(拦截器、格式化程序、视图控制器和其他特性) ,可以添加您自己的 WebMvcConfigurer类型的@Configuration 类,但不要添加@EnableWebMvc。
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
.
如果你想完全控制 Spring MVC,你可以添加你自己的@Configuration 注释@EnableWebMvc,或者添加自己的
@Configuration
-annotatedDelegatingWebMvcConfiguration
中的Javadoc中所述@EnableWebMvc
。
总结一下:如果我们需要定制适合当前开发需求的springmvc,那么有两种方法:
- (推荐)在使用@Configuration注解的配置类中,实现WebMvcConfigurer接口并重写对应方法或者添加一个用户自定义的WebMvcConfigurer组件,但不能使用@EnableWebMvc
- 使用@Configuration注解的同时,使用@EnableWebMvc
深入理解
首先我们得知道:(推荐使用在自动配置的基础上进行更多定制,即同时使用自动配置以及用户自定义配置)
SpringBoot会默认自动配置组件,在自动配置组件的时候,首先会查看IOC容器中是否有用户自定义配置的(即,在@Configuration配置类中,用户使用@Bean添加进容器中的组件),如果有就用用户配置的,如果没有就用自动配置的;如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来。
示例代码
这里是推荐方法的使用,至于全面接管的使用,后面再更新吧(如果你看到了这句话,那还没有更新.........)
- 第一种,实现WebMvcConfigurer接口并重写对应方法
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
// 移除url中分号:设置为false,不移除;这样,才能从url中取出矩阵变量的值
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
- 第二种:在配置类中,用户使用WebMvcConfigurer定制化SpringMVC的功能,并添加到容器中
@Configuration
public class WebConfig /*implements WebMvcConfigurer*/ {
// WebMvcConfigurer定制化SpringMVC的功能
@Bean
public WebMvcConfigurer webMvcConfigurer(){
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper = new UrlPathHelper();
// 不移除;后面的内容。矩阵变量功能就可以生效
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}
自动配置原理(推荐方法)
WebMvcConfigurer
我们知道springboot是自动配置类是WebMvcAutoConfiguration.class:
@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 {
......
}
WebMvcAutoConfiguration.class中有一个静态类WebMvcAutoConfigurationAdapter,实现了WebMvcConfigurer:
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {...}
WebMvcAutoConfigurationAdapter类是实现了WebMvcConfigurer接口,WebMvcConfigurer中提供了许多默认实现的方法,我们正是通过对这些方法的重写,来达到定制的目的。
public interface WebMvcConfigurer { default void configurePathMatch(PathMatchConfigurer configurer) {
}
.......
}
从注解@Import(EnableWebMvcConfiguration.class)看到,WebMvcAutoConfiguration导入了一个配置等效于@EnableWebMvc的配置类,这个类继承了DelegatingWebMvcConfiguration,而DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport。
DelegatingWebMvcConfiguration这个类的作用:其实是调用WebMvcConfigurerComposite这个类中的方法,目的是同时加载自动配置和用户自定义的配置
/**
* A subclass of {@code WebMvcConfigurationSupport} that detects and delegates
* to all beans of type {@link WebMvcConfigurer} allowing them to customize the
* configuration provided by {@code WebMvcConfigurationSupport}. This is the
* class actually imported by {@link EnableWebMvc @EnableWebMvc}.
*
* @author Rossen Stoyanchev
* @since 3.1
*WebMvcConfigurationSupport的子类,它检测并委托给WebMvcConfigurer类型的所有bean,允许它们自定义WebMvcConfigurationSupport提供的配置。 这是由@EnableWebMvc实际导入的@EnableWebMvc
*/
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { 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的相关配置bean,包括我们自己配置的和SpringBoot给我们自动配置的,即这里完成了在自动配置的基础上增加我们自定义的配置。下面给出两个示例方法:
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
// 从容器中获取所有自定义配置bean
this.configurers.addWebMvcConfigurers(configurers);
}
} @Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
// 遍历容器中中相关配置并调用
this.configurers.configurePathMatch(configurer);
}
查看configurePathMatch()方法:
将各种自定义配置bean(即WebMvcConfigurer对象)添加到delegates中,并将所有的WebMvcConfigurer相关配置使用对应的方法进行遍历调用(包括springboot自动配置的和我们用户自定义配置的)。
class WebMvcConfigurerComposite implements WebMvcConfigurer { private final List<WebMvcConfigurer> delegates = new ArrayList<>(); public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.delegates.addAll(configurers);
}
} @Override
public void configurePathMatch(PathMatchConfigurer configurer) {
// 遍历调用实现,实现默认的配置以及自定义的配置
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configurePathMatch(configurer);
}
}
....
}
总结1
所有的WebMvcConfiguration都会被调用,包括springboot自动配置的内容以及我们自己定义的配置。
为什么不能使用@EnableWebMvc(完全控制Spring MVC)
完全控制Spring MVC:SpringBoot对SpringMVC的自动配置失效,所有配置都需要用户自己去配置。
前面提到,如果使用第一种方法的话,就不能使用@EnableWebMvc注解,从WebMvcConfigurer的实现类WebMvcAutoConfigurationAdapter所在的springboot自动配置类WebMvcAutoConfiguration可以看到:
@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 {
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
只有当容器里面没有WebMvcConfigurationSupport这个组件时,才能使用SpringBoot的自动配置。所以,当我们使用第一种自动配置+自定义配置时,不能使用@EnableWebMvc注解的原因就在此。(从自动配置类WebMvcAutoConfiguration直观分析)
进一步理解,加入@EnableWebMvc注解后SpringMVC的所有自动配置失效的原理:
- 查看@EnableWebMvc注解的定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
- 这个要导入DelegatingWebMvcConfiguration组件:
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {...}
可以看到DelegatingWebMvcConfiguration是继承WebMvcConfigurationSupport,也就是说如果使用注解@EnableWebMvc,就会向容器添加组件DelegatingWebMvcConfiguration,等同于导入了WebMvcConfigurationSupport,这与springboot自动配置类使用的条件冲突,导致自动配置失效。
总结2
@EnableWebMvc将WebMvcConfigurationSupport组件导入进容器中来了,会导致自动配置失效。
Springboot MVC 自动配置的更多相关文章
- springboot mvc自动配置(三)初始化mvc的组件
所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 在springboot mvc自动配置的时候,获得了DispatcherServlet和 ...
- springboot mvc自动配置(目录)
对于长时间基于spring框架做web开发的我们,springmvc几乎成为了开发普通web项目的标配.本系列文章基于快速启动的springboot,将从源码角度一点点了解springboot中mvc ...
- springboot mvc自动配置(一)自动配置DispatcherServlet和DispatcherServletRegistry
所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 springboot的自动配置基于SPI机制,实现自动配置的核心要点就是添加一个自动配置 ...
- 全网最深分析SpringBoot MVC自动配置失效的原因
前言 本来没有计划这一篇文章的,只是在看完SpringBoot核心原理后,突然想到之前开发中遇到的MVC自动失效的问题,虽然网上有很多文章以及官方文档都说明了原因,但还是想亲自看一看,本以为很简单的事 ...
- springboot mvc自动配置(二)注册DispatcherServlet到ServletContext
所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 上一篇文章中,我们看到了DispatcherServlet和DispatcherServ ...
- spring-boot spring-MVC自动配置
Spring MVC auto-configuration Spring Boot 自动配置好了SpringMVC 以下是SpringBoot对SpringMVC的默认配置:==(WebMvcAuto ...
- SpringBoot的自动配置
1.根据条件来装配bean,SpringBoot的自动配置,根据条件进行自动配置. 首先创建一个接口,如下所示: package com.bie.encoding; /** * * @Descript ...
- springboot(六)自动配置原理和@Conditional
官方参考的配置属性:https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#common-appl ...
- 关于SpringBoot的自动配置和启动过程
一.简介 Spring Boot简化了Spring应用的开发,采用约定大于配置的思想,去繁从简,很方便就能构建一个独立的.产品级别的应用. 1.传统J2EE开发的缺点 开发笨重.配置繁多复杂.开发效率 ...
随机推荐
- 【HTML】基础
HTML基础 2019-07-23 10:16:28 by冲冲 在线编辑HTML/CSS/JS效果,实时查看效果 https://c.runoob.com/front-end/61 1. 概念 ① ...
- 链式调用Builder
使用Lombok实现链式调用 1.静态调用 User对象: 对象中必须有一个值不为空staticname作为指定的参数并调用对象 @Accessors(chain = true) @Getter @S ...
- Java LinkedList小记
1. 基本用法 LinkedList实现了List.Deque.Queue接口,可以按照队列.栈和双端队列的方式进行操作.LinkedList有两个构造方法,一个是默认构造,另一个接受Collecti ...
- Linux——防火墙、SELinux规则
一.Firewalld防火墙规则 防火墙的作用:放行或者阻拦某些服务.端口 1.防火墙的简单操作 # 1.查看防火墙状态 systemctl status firewalld # 2.关闭防火墙 sy ...
- intent.getSerializableExtra(转)
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
- clickhouse使用的一点总结
clickhouse据说是用在大数据量的olap场景列式存储数据库,也有幸能够用到它在实际场景中落地.本篇就来说说简单的使用心得吧. 1. 整体说明 架构啥的,就不多说了,列式存储.大数据量.高性能. ...
- R语言矩阵相关性计算及其可视化?
目录 1. 矩阵相关性计算方法 base::cor/cor.test psych::corr.test Hmisc::rcorr 其他工具 2. 相关性矩阵转化为两两相关 3. 可视化 corrplo ...
- R 语言实战-Part 5-2笔记
R 语言实战(第二版) part 5-2 技能拓展 ----------第21章创建包-------------------------- #包是一套函数.文档和数据的合集,以一种标准的格式保存 #1 ...
- MetaboAnalyst的多组学分析
MetaboAnalyst是做代谢的R包,功能十分强大.也开发了web版本,代谢组学的分析这里不介绍,主要讲讲它开发的多组学分析的相关内容. 既然是做代谢的工具,即使是增加了多组学内容,肯定也是以代谢 ...
- Python队列queue模块
Python中queue模块常用来处理队列相关问题 队列常用于生产者消费者模型,主要功能为提高效率和程序解耦 1. queue模块的基本使用和相关说明 # -*- coding:utf-8 -*- # ...