擴展、接管MVC都不會,還會用Spring Boot?
- 2020 年 10 月 13 日
- 筆記
- JAVA, springboot, 碼猿技術專欄
持續原創輸出,點擊上方藍字關注我
目錄
-
前言 -
Spring Boot 版本 -
如何擴展MVC? -
如何自定義一個攔截器? -
什麼都不配置為什麼依然能運行MVC相關的功能? -
如何全面接管MVC?【不推薦】 -
為什麼@EnableWebMvc一個註解就能夠全面接管MVC? -
Spring Boot相關資料 -
總結
前言
自從用了Spring Boot是否有一個感覺,以前MVC的配置都很少用到了,比如視圖解析器,攔截器,過濾器等等,這也正是Spring Boot好處之一。
但是往往Spring Boot提供默認的配置不一定適合實際的需求,因此需要能夠定製MVC的相關功能,這篇文章就介紹一下如何擴展和全面接管MVC。
Spring Boot 版本
本文基於的Spring Boot的版本是2.3.4.RELEASE
。
如何擴展MVC?
在這裡需要聲明一個前提:配置類上沒有標註@EnableWebMvc
並且沒有任何一個配置類繼承了WebMvcConfigurationSupport
。至於具體原因,下文會詳細解釋。
擴展MVC其實很簡單,只需要以下步驟:
-
創建一個MVC的配置類,並且標註 @Configuration
註解。 -
實現 WebMvcConfigurer
這個接口,並且實現需要的方法。
WebMvcConfigurer
這個接口中定義了MVC相關的各種組件,比如攔截器,視圖解析器等等的定製方法,需要定製什麼功能,只需要實現即可。
在Spring Boot之前的版本還可以繼承一個抽象類WebMvcConfigurerAdapter
,不過在2.3.4.RELEASE
這個版本中被廢棄了,如下:
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {}
舉個栗子:現在要添加一個攔截器,使其在Spring Boot中生效,此時就可以在MVC的配置類重寫addInterceptors()
方法,如下:
/**
* MVC擴展的配置類,實現WebMvcConfigurer接口
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor;
/**
* 重寫addInterceptors方法,注入自定義的攔截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(repeatSubmitInterceptor).excludePathPatterns("/error");
}
}
操作很簡單,除了攔截器,還可以定製視圖解析,資源映射處理器等等相關的功能,和Spring MVC很類似,只不過Spring MVC是在XML
文件中配置,Spring Boot是在配置類中配置而已。
什麼都不配置為什麼依然能運行MVC相關的功能?
早期的SSM架構中想要搭建一個MVC其實挺複雜的,需要配置視圖解析器,資源映射處理器,DispatcherServlet
等等才能正常運行,但是為什麼Spring Boot僅僅是添加一個WEB
模塊依賴即能正常運行呢?依賴如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
其實這已經涉及到了Spring Boot高級的知識點了,在這裡就簡單的說一下,Spring Boot的每一個starter
都會有一個自動配置類,什麼是自動配置類呢?自動配置類就是在Spring Boot項目啟動的時候會自動加載的類,能夠在啟動期間就配置一些默認的配置。WEB
模塊的自動配置類是WebMvcAutoConfiguration
。
WebMvcAutoConfiguration
這個配置類中還含有如下一個子配置類WebMvcAutoConfigurationAdapter
,如下:
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
WebMvcAutoConfigurationAdapter
這個子配置類實現了WebMvcConfigurer
這個接口,這個正是MVC擴展接口,這個就很清楚了。自動配置類是在項目啟動的時候就加載的,因此Spring Boot會在項目啟動時加載WebMvcAutoConfigurationAdapter
這個MVC擴展配置類,提前完成一些默認的配置(比如內置了默認的視圖解析器,資源映射處理器等等),這也就是為什麼沒有配置什麼MVC相關的東西依然能夠運行。
如何全面接管MVC?【不推薦】
全面接管MVC是什麼意思呢?全面接管的意思就是不需要Spring Boot自動配置,而是全部使用自定義的配置。
全面接管MVC其實很簡單,只需要在配置類上添加一個@EnableWebMvc
註解即可。還是添加攔截器,例子如下:
/**
* @EnableWebMvc:全面接管MVC,導致自動配置類失效
*/
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private RepeatSubmitInterceptor repeatSubmitInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加攔截器
registry.addInterceptor(repeatSubmitInterceptor).excludePathPatterns("/error");
}
}
一個註解就能全面接口MVC,是不是很爽,不過,不建議使用。
為什麼@EnableWebMvc一個註解就能夠全面接管MVC?
what???為什麼呢?上面剛說過自動配置類WebMvcAutoConfiguration
會在項目啟動期間加載一些默認的配置,這會怎麼添加一個@EnableWebMvc
註解就不行了呢?
其實很簡單,@EnableWebMvc
源碼如下:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
其實重要的就是這個@Import(DelegatingWebMvcConfiguration.class)
註解了,Spring中的註解,快速導入一個配置類DelegatingWebMvcConfiguration
,源碼如下:
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {}
明白了,@EnableWebMvc
這個註解實際上就是導入了一個WebMvcConfigurationSupport
子類型的配置類而已。
而WEB模塊的自動配置類有這麼一行註解@ConditionalOnMissingBean(WebMvcConfigurationSupport.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 {
這個註解@ConditionalOnMissingBean
什麼意思呢?簡單的說就是IOC容器中沒有指定的Bean
這個配置才會生效。
一切都已經揭曉了,@EnableWebMvc
導入了一個WebMvcConfigurationSupport
類型的配置類,導致了自動配置類WebMvcAutoConfiguration
標註的@@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
判斷為false
了,從而自動配置類失效了。
總結
擴展和全面接管MVC都很簡單,但是不推薦全面接管MVC,一旦全面接管了,WEb模塊的這個starter
將沒有任何意義,一些全局配置文件中與MVC相關的配置也將會失效。