热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringbootMVC自动配置

SpringbootMVC自动配置官方文档阅读https:docs.spring.iospring-bootdocscurrentreferencehtml

Springboot MVC 自动配置

Springboot MVC 自动配置

官方文档阅读

https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.servlet.spring-mvc.auto-configuration

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 and BeanNameViewResolver beans.
  • Support for serving static resources, including support for WebJars (covered later in this document).
  • Automatic registration of Converter, GenericConverter, and Formatter 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-annotated DelegatingWebMvcConfiguration中的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

  1. 我们知道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 {
        ......
    }
    
  2. WebMvcAutoConfiguration.class中有一个静态类WebMvcAutoConfigurationAdapter实现了WebMvcConfigurer

    	@Configuration(proxyBeanMethods = false)
    	@Import(EnableWebMvcConfiguration.class)
    	@EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class })
    	@Order(0)
    	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {...}
    
  3. WebMvcAutoConfigurationAdapter类是实现了WebMvcConfigurer接口,WebMvcConfigurer中提供了许多默认实现的方法,我们正是通过对这些方法的重写,来达到定制的目的。

    public interface WebMvcConfigurer {
        
    	default void configurePathMatch(PathMatchConfigurer configurer) {
    	}
        .......
    }
    
  4. 从注解@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 configurers) {
    		if (!CollectionUtils.isEmpty(configurers)) {
    			this.configurers.addWebMvcConfigurers(configurers);
    		}
    	}
        
       ........
    }
    

    我们随机选择这个类中任意一个方法,并进入到调用的对应WebMvcConfigurerComposite类中的方法,可以发现:

    这个类的方法,将实现所有WebMvcConfigurer的相关配置bean,包括我们自己配置的和SpringBoot给我们自动配置的,即这里完成了在自动配置的基础上增加我们自定义的配置。下面给出两个示例方法:

    	@Autowired(required = false)
    	public void setConfigurers(List 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 delegates = new ArrayList<>();
    
    	public void addWebMvcConfigurers(List 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的所有自动配置失效的原理:

  1. 查看@EnableWebMvc注解的定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
  1. 这个要导入DelegatingWebMvcConfiguration组件:
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {...}

可以看到DelegatingWebMvcConfiguration是继承WebMvcConfigurationSupport,也就是说如果使用注解@EnableWebMvc,就会向容器添加组件DelegatingWebMvcConfiguration,等同于导入了WebMvcConfigurationSupport,这与springboot自动配置类使用的条件冲突,导致自动配置失效。

总结2

@EnableWebMvc将WebMvcConfigurationSupport组件导入进容器中来了,会导致自动配置失效。


推荐阅读
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 本文为Codeforces 1294A题目的解析,主要讨论了Collecting Coins整除+不整除问题。文章详细介绍了题目的背景和要求,并给出了解题思路和代码实现。同时提供了在线测评地址和相关参考链接。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
author-avatar
马芷靈
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有