詳解Spring Boot中如何自定義SpringMVC配置
前言
在 Spring Boot 框架中隻需要在項目中引入 spring-boot-starter-web 依賴,SpringMVC 的一整套東西就會自動給我們配置好;但是,真實的項目環境比較復雜,系統自帶的配置不一定滿足我們的需求,往往我們還需要結合實際情況自定義配置。
自定義配置就有講究瞭,由於 Spring Boot 的版本變遷,加上這一塊本身就有幾個不同寫法,容易搞混。
一、SpringBoot 中 SpringMVC 配置概述
首先我們需要明確,跟自定義 SpringMVC 相關的類和註解主要有如下四個:
- WebMvcConfigurerAdapter
- WebMvcConfigurer
- WebMvcConfigurationSupport
- @EnableWebMvc
這四個中,除瞭 @EnableWebMvc 是註解外,WebMvcConfigurerAdapter 和 WebMvcConfigurationSupport 是兩個類,WebMvcConfigurer 是一個接口。裡邊的方法看起來好像都類似,但是實際使用效果卻大不相同。
二、WebMvcConfigurerAdapter 抽象類
我們先來看 WebMvcConfigurerAdapter,這個是在 Spring Boot 1.x 中我們自定義 SpringMVC 時繼承的一個抽象類。
這個抽象類本身是實現瞭 WebMvcConfigurer 接口,然後抽象類裡邊都是空方法,我們來看一下這個類的聲明:
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { //各種 SpringMVC 配置的方法 }
再來看看這個類的註釋:
/** * 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 */
這段註釋關於這個類說的很明白瞭。
同時我們也看到,從 Spring5 開始,由於我們要使用 Java8,而 Java8 中的接口允許存在 default 方法,因此官方建議我們直接實現 WebMvcConfigurer 接口,而不是繼承 WebMvcConfigurerAdapter。
也就是說,在 Spring Boot 1.x 的時代,如果我們需要自定義 SpringMVC 配置,直接繼承 WebMvcConfigurerAdapter 類即可。
三、WebMvcConfigurer 接口
如上所述,WebMvcConfigurer 是在 Spring Boot 2.x 中實現自定義配置的方案。
WebMvcConfigurer 是一個接口;接口中的方法和 WebMvcConfigurerAdapter 中定義的空方法其實一樣,所以用法上來說,基本上沒有差別。
從 Spring Boot 1.x 切換到 Spring Boot 2.x ,隻需要把繼承類改成實現接口即可。
四、WebMvcConfigurationSupport 類-自定義配置
在 Spring 框架中,可以通過 Spring 和 SpringMVC 的XML 配置文件設置MVC 框架;在 Spring Boot 中自定義 SpringMVC 配置時,可以通過繼承 WebMvcConfigurationSupport 類來實現。
在 WebMvcConfigurationSupport 類中,提供瞭用 Java 配置 SpringMVC 所需要的所有方法。我們來看一下這個方法的摘要:
WebMvcConfigurationSupport 類方法列表
有一點眼熟,可能有小夥伴發現瞭,這裡的方法其實和前面兩個類中的方法基本是一樣的。
在這裡首先大傢需要明確的是,WebMvcConfigurationSupport 類本身是沒有問題的,我們自定義 SpringMVC 的配置是可以通過繼承 WebMvcConfigurationSupport 來實現的。
五、WebMvcAutoConfiguration 配置類 – 自動化配置
Spring Boot 中,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 { }
我們從這個類的註解中可以看到,它的生效條件有一條,就是當不存在 WebMvcConfigurationSupport 的實例時,這個自動化配置才會生生效。
因此,如果我們在 Spring Boot 中自定義 SpringMVC 配置時選擇瞭繼承 WebMvcConfigurationSupport,就會導致 Spring Boot 中 SpringMVC 的自動化配置失效。
Spring Boot 給我們提供瞭很多自動化配置,很多時候當我們修改這些配置的時候,並不是要全盤否定 Spring Boot 提供的自動化配置。
我們可能隻是針對某一個配置做出修改,其他的配置還是按照 Spring Boot 默認的自動化配置來。
而繼承 WebMvcConfigurationSupport 來實現對 SpringMVC 的配置會導致所有的 SpringMVC 自動化配置失效,因此,一般情況下我們不選擇這種方案。
六、@EnableWebMvc 註解
最後還有一個 @EnableWebMvc 註解,這個註解很好理解,它的作用就是啟用 WebMvcConfigurationSupport。
我們來看看這個註解的定義:
/** * Adding this annotation to an {@code @Configuration} class imports the Spring MVC * configuration from {@link WebMvcConfigurationSupport}, e.g.:
可以看到,加瞭這個註解,就會自動導入 WebMvcConfigurationSupport。
所以在 Spring Boot 中,我們也不建議使用 @EnableWebMvc 註解,因為它一樣會導致 Spring Boot 中的 SpringMVC 自動化配置失效。
七、總結
不知道上面的解釋小夥伴有沒有看懂?我再簡單總結一下:
- Spring Boot 1.x 中,自定義 SpringMVC 配置可以通過繼承 WebMvcConfigurerAdapter 來實現。
- Spring Boot 2.x 中,自定義 SpringMVC 配置可以通過實現 WebMvcConfigurer 接口來完成。
如果在 Spring Boot 中使用繼承 WebMvcConfigurationSupport 來實現自定義 SpringMVC 配置,或者在 Spring Boot 中使用瞭 @EnableWebMvc 註解,都會導致 Spring Boot 中默認的 SpringMVC 自動化配置失效。
在純 Java 配置的 SSM 環境中,如果我們要自定義 SpringMVC 配置,有兩種辦法:
- 第一種就是直接繼承自 WebMvcConfigurationSupport 來完成 SpringMVC 配置
- 還有一種方案就是實現 WebMvcConfigurer 接口來完成自定義 SpringMVC 配置
果使用第二種方式,則需要給 SpringMVC 的配置類上額外添加 @EnableWebMvc 註解,表示啟用WebMvcConfigurationSupport,這樣配置才會生效。
換句話說,在純 Java 配置的 SSM 中,如果你需要自定義 SpringMVC 配置,你離不開 WebMvcConfigurationSupport ,所以在這種情況下建議通過繼承 WebMvcConfigurationSupport 來實現自動化配置。
推薦閱讀:
- SpringBoot嵌入式Servlet容器與定制化組件超詳細講解
- 解決springboot 2.x 裡面訪問靜態資源的坑
- 教你用Java SpringBoot如何解決跨域
- 淺談SpringBoot如何自定義Starters
- Spring Boot簡介與快速搭建詳細步驟