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
ContentNegotiatingViewResolverandBeanNameViewResolverbeans. - Support for serving static resources, including support for WebJars (covered later in this document).
- Automatic registration of
Converter,GenericConverter, andFormatterbeans. - Support for
HttpMessageConverters(covered later in this document). - Automatic registration of
MessageCodesResolver(covered later in this document). - Static
index.htmlsupport. - Automatic use of a
ConfigurableWebBindingInitializerbean (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开发的缺点 开发笨重.配置繁多复杂.开发效率 ...
随机推荐
- GPG 使用指南
加密与签名 在传输信息时,会面临两个典型的问题: 如何保证发出的消息,只能被预期的接收人获取? 如何保证收到的消息,确实由预期的发送人发出? 这两个问题不难理解.例如发送的邮件可能会被监听,诈骗分子可 ...
- Codeforces 566E - Restoring Map(bitset 优化构造)
Codeforces 题目传送门 & 洛谷题目传送门 本来说好的不做,结果今早又忍不住开了道题/qiao 我们称度为 \(1\) 的点为叶节点,度大于 \(1\) 的点为非叶节点. 首先考虑如 ...
- Codeforces 436D - Pudding Monsters(dp)
Codeforces 题目传送门 & 洛谷题目传送门 u1s1 这题数据范围有点迷惑啊--乍一看 \(\mathcal O(nm)\) 过不去,还以为是正解是 \(\mathcal O(n+m ...
- NOIP2021 游记
不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分不要挂分释迦牟尼脚绽莲花菩提达摩你真伟大天上天下唯我独尊如来佛祖太上老君耶稣耶稣 ...
- GWAS数据分析常见的202个问题?
生信其实很简单,就是用别人的工具调参就行了.生信也很折腾,哪一步都可能遇到问题,随时让你疯掉(老辩证法了~).但是,你遇到的问题大部分人也都经历过.这时,检索技能就显得很重要了.平时Biostar和S ...
- python20判断变量是否存在
python中检测某个变量是否有定义 第一种方法使用内置函数locals(): locals():获取已定义对象字典 'testvar' in locals().keys() 第二种方法使用内置函数d ...
- 学习java的第十一天
一.今日收获 1.学习java完全学习手册2.9.3循环结构的内容并验证例题 2.观看哔哩哔哩上的教学视频 二.今日问题 1.基本没有 三.明日目标 1.继续完成2.9.3循环结构的例题 2.哔哩哔哩 ...
- Redis - 1 - linux中使用docker-compose安装Redis - 更新完毕
0.前言 有我联系方式的那些半吊子的人私信问我:安装Redis有没有更简单的方式,网上那些文章和视频,没找到满意的方法,所以我搞篇博客出来说明一下我的安装方式吧 1.准备工作 保证自己的linux中已 ...
- SQLITE_BTREE_H
sqlite3.c, 237436行 = 全部源文件,找东西比多文件查找方便多了:-),字符串查找一点都不慢. 不要太害怕,SQLite说它的代码里有非常多是用来做数据完整性检查和测试的.但愿B树,虚 ...
- IT四大名著
标题耸人听闻,sorry. CPU.操作系统.编译器和数据库我都不会.我英语也不行,但我认识所有的字母.:-) 万一有人感兴趣呢?https://sqlite.org/doclist.htmlThe ...