在SpringBoot 中如何自定义 SpringMVC 配置?

一、引言

用过SpringBoot框架开发的应该都知道用 SpringBoot 开发非常方便,完全不需要自己配置,比手动用 Spring 搭建 SSM 框架,简直就是不能比。当我们用 SpringBoot 开发 Web 项目时,只需要在项目中引入 spring-boot-starter-web 这个依赖,SpringMVC 的一整套东西就会被自动配置好,我们不用做其他复杂的配置。这就是SpringBoot的一大特性——自动配置。

但在日常的工作开发中,由于项目环境比较复杂,可能有时候SpringBoot自带的默认配置不一定能满足我们的需求,这种情况下,我们该怎么办呢?是不是要结合实际的项目来做一些自定义的配置。下面我们就来看看如何自定义 SpringMVC 的配置。

二、SpringMVC配置相关的类和注解

首先我们需要知道,跟自定义 SpringMVC 相关的类和注解主要有如下四个:

WebMvcConfigurerAdapter
WebMvcConfigurer  // 接口
WebMvcConfigurationSupport
@EnableWebMvc

上面这四个,前三个中,两个类一个接口,最后一个是注解。大家可以各个类中看一下,可以发现里边的方法看起来好像都类似,但是实际使用效果却大不相同,因此很容易搞混,下面就来逐一介绍一下。

1、WebMvcConfigurerAdapter

首先来看 WebMvcConfigurerAdapter,这个类出现在Spring 3.1的版本中,如果你用的是 SpringBoot 1.x 开发项目,我们在自定义 SpringMVC 时需要继承这个抽象类,这个抽象类本身是实现了 WebMvcConfigurer 接口,然后抽象类里边都是空方法,下面看一下这个类的声明:


/**
 * An implementation of {@link WebMvcConfigurer} with empty methods allowing
 * subclasses to override only the methods they're interested in.
 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
 * possible by a Java 8 baseline) and can be implemented directly without the
 * need for this adapter
 */
@Deprecated  // 标记已经过时了
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {

 	//各种 SpringMVC 配置的方法,而且都是空方法
	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
	}
	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer 
										configurer) {
	}
	
    ......
}

我们来关注一下这个类上面的注释,对于这个类的说明是不是一目了然。同时我们也看到,从 Spring5 开始,由于我们要使用 Java8,而 Java8 中的接口允许存在 default 方法,因此官方建议我们直接实现 WebMvcConfigurer 接口,而不是继承 WebMvcConfigurerAdapter

也就是说,如果你的项目是用 Spring Boot 1.x 版本,如果需要自定义SpringMVC 配置,直接继承 WebMvcConfigurerAdapter 类即可。

这里多说一句,之前有个小伙伴从github上下载了我的样例代码,死活运行不起来,后来我让他把报错信息发我看一下,就是这个地方的原因。我的样例用的是SpringBoot 2.0.x,而他的环境用的是SpringBoot 1.0.x,从 Spring Boot 1.x 切换到 Spring Boot 2.x需要把继承类改成实现接口。由于WebMvcConfigurer 是一个接口,接口中的方法和 WebMvcConfigurerAdapter 中定义的空方法一样(是它的实现嘛~~),所以从用法上来说,基本上没有差别,但各个版本之间的差别还是要注意一下。

2、WebMvcConfigurer

根据上面的介绍,我们知道 WebMvcConfigurer 是在 Spring Boot 2.x 中实现自定义配置的方案,不用做过多介绍了吧~~~~

3、WebMvcConfigurationSupport

前面两个都好理解,还有一个 WebMvcConfigurationSupport ,这个类又是干什么用的呢?

不知道大家有没有用过Servlet3.0和纯注解的方式来搭建过SSM框架,如果没有的话,可以自己尝试一下,会让你受益匪浅。

当我们用纯注解来搭建SSM框架时,在自定义SpringMVC 配置的时候,就是通过继承 WebMvcConfigurationSupport 类来实现的。在 WebMvcConfigurationSupport 类中,提供了用 Java 配置 SpringMVC 所需要的所有方法。下面来看一下这个方法的摘要:

在这里插入图片描述
如果你看过上面两个类的源码的话,再看这个类,肯定觉得眼熟,你再仔细看一下,这里的方法是不是和前面两个类中的方法基本是一样的???

在这里首先大家需要明确的是,WebMvcConfigurationSupport 类本身是没有问题的,我们自定义SpringMVC 的配置是可以通过继承 WebMvcConfigurationSupport 来实现的。但是继承 WebMvcConfigurationSupport 这种操作一般只在 Java 配置的 SSM 项目中使用,SpringBoot 中基本上不会这么写,为什么呢?

因为在 SpringBoot 中,SpringMVC 相关的自动化配置是在 WebMvcAutoConfiguration 这个配置类中实现的,那么我们来看看这个配置类的生效条件:

@Configuration
@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 {
}

我们从这个类的注解中可以看到,SpringBoot 自动配置的生效条件有一个就是:当不存在 WebMvcConfigurationSupport 的实例时,这个自动化配置才会生效。因此,如果我们在 SpringBoot 中自定义 SpringMVC 配置时选择了继承 WebMvcConfigurationSupport,就会导致 SpringBoot 中 默认的SpringMVC 的自动化配置失效。

SpringBoot 给我们提供了很多自动化配置,大部分时间里,当我们需要修改这些配置的时候,并不是要全盘否定 SpringBoot 提供的自动化配置,我们可能只是针对某一个配置做出修改,其他的配置还是按照 SpringBoot 默认的自动化配置来,而继承 WebMvcConfigurationSupport 来实现对 SpringMVC 的配置会导致所有的 SpringMVC 自动化配置失效,因此,一般情况下我们不选择继承WebMvcConfigurationSupport

但我们在用 Java 搭建的 SSM 项目中(不用SpringBoot,如何搭建一个SpringWeb工程?),因为本身就没什么自动化配置,所以可以使用继承 WebMvcConfigurationSupport

4、@EnableWebMvc

最后还有一个 @EnableWebMvc 注解,这个注解很好理解,它的作用就是在SpringBoot中启用WebMvcConfigurationSupport

我们来看看这个注解的定义:

/**
 * Adding this annotation to an {@code @Configuration} class imports 
 * the Spring MVC configuration from {@link WebMvcConfigurationSupport}, e.g.:
 * /

可以看到,加了这个注解,就会自动导入 WebMvcConfigurationSupport,所以在 SpringBoot 中,我们也不建议使用 @EnableWebMvc 注解,因为它一样会导致 SpringBoot 中的 SpringMVC 自动化配置失效。因为WebMvcAutoConfiguration 生效的条件就是不能有WebMvcConfigurationSupport的出现。

三、小结

上面对 WebMvcConfigurerAdapterWebMvcConfigurerWebMvcConfigurationSupport、 @EnableWebMvc这四个知识做了详细的介绍。下面来对它们做一下总结:

Spring Boot 1.x 中,自定义SpringMVC 配置可以通过继承 WebMvcConfigurerAdapter 来实现。
Spring Boot 2.x 中,自定义SpringMVC 配置可以通过实现 WebMvcConfigurer 接口来完成。
如果在 SpringBoot 中使用继承 WebMvcConfigurationSupport 来实现自定义 SpringMVC 配置,
或者在 SpringBoot 中使用了 @EnableWebMvc 注解,都会导致 SpringBoot 中默认配置的 SpringMVC 自动化配置失效。

在纯 Java 配置的 SSM 环境中,如果我们要自定义 SpringMVC 配置,有两种办法,第一种就是直接继承自 WebMvcConfigurationSupport 来完成 SpringMVC 配置,还有一种方案就是实现 WebMvcConfigurer 接口来完成自定义 SpringMVC 配置,如果使用后一种方式,我们需要给 SpringMVC 的配置类上额外添加 @EnableWebMvc 注解,表示启用 WebMvcConfigurationSupport,这样配置才会生效。换句话说,在纯 Java 配置的 SSM 中,如果你需要自定义 SpringMVC 配置,你离不开 WebMvcConfigurationSupport ,所以在这种情况下建议通过继承 WebMvcConfigurationSupport 来实现自动化配置。

这里多解释一下:在纯Java配置的SSM中,实现 WebMvcConfigurer 接口来完成自定义 SpringMVC 配置,为什么一定要开启@EnableWebMvc注解呢?

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

来看一下这个注解,使用这个注解,就是往Spring容器中添加了DelegatingWebMvcConfiguration这个Bean。再看一下DelegatingWebMvcConfiguration这个类,有这样一个属性WebMvcConfigurerComposite,维护着WebMvcConfigurer的集合,有点类似组合模式。初始化DelegatingWebMvcConfiguration时如果发现了WebMvcConfigurer的实现类,就注入到WebMvcConfigurerComposite中,这样就把我们实现了WebMvcConfigurer的类和@EnableWebMvc联系到一起了。

发布了123 篇原创文章 · 获赞 230 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zxd1435513775/article/details/102928277