SpringBoot2.x中WebMvcConfigurerAdapter已過時,使用WebMvcConfigurationSupport替換時自動配置失效
1、我們在使用SpringBoot2.x時,想要自己擴充套件SpringMvc的功能,在使用WebMvcConfigurerAdapter發現,該方法已過時。
然後通過百度,發現很多人都說可以用WebMvcConfigurationSupport來替代,於是我們很興奮的寫了一段程式碼測試。
@Configuration public class MyMvcConfig extends WebMvcConfigurationSupport { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); } }
執行完發現一個新坑,Spring Boot的WebMvc自動配置失效了,我們訪問不到靜態資源(js,css等)了,然後查詢資料發現,這是因為WebMvc的自動配置都在WebMvcAutoConfiguration類中,
@Configuration @ConditionalOnWebApplication( type = Type.SERVLET ) @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class}) @ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) @AutoConfigureOrder(-2147483638) @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}) public class WebMvcAutoConfiguration {
但是類中有@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})這個註解,然而這個註解的意思是一旦在容器中檢測到WebMvcConfigurationSupport這個類,WebMvcAutoConfiguration類中的配置就都不生效,只有在我們的的容器中沒有這個元件的時候,自動配置類才會生效。所以一旦我們自己寫的配置類繼承了WebMvcConfigurationSupport,就相當於我們的容器中已經匯入了WebMvcConfigurationSupport這個元件,所以預設配置都不會生效,都得自己在配置檔案中配置。
@Configuration
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
public static final String DEFAULT_PREFIX = "";
public static final String DEFAULT_SUFFIX = "";
private static final String[] SERVLET_LOCATIONS = new String[]{"/"};
public WebMvcAutoConfiguration() {
}
@Configuration
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({S
那麼我們不想使WebMvc的自動配置失效,該怎麼辦呢?
我們可以實現WebMvcConfigurer介面,這個介面的方法都加了jdk1.8的 default方法修飾,不強制實現所有的方法,可以根據實際實現相關的方法
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.web.servlet.config.annotation;
import java.util.List;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
public interface WebMvcConfigurer {
default void configurePathMatch(PathMatchConfigurer configurer) {
}
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
default void addFormatters(FormatterRegistry registry) {
}
default void addInterceptors(InterceptorRegistry registry) {
}
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
default void addCorsMappings(CorsRegistry registry) {
}
default void addViewControllers(ViewControllerRegistry registry) {
}
default void configureViewResolvers(ViewResolverRegistry registry) {
}
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
package com.boot.test.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @ClassName MyMvcConfig
* @Description TODO
* @Author shanzz
* @Date 2018/12/28 17:01
* @Version 1.0
**/
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
2、使用@EnableWebMvc 使WebMvc自動配置失效原因
進入@EnableWebMvc可以發現
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
這裡匯入了DelegatingWebMvcConfiguration.class
進入DelegatingWebMvcConfiguration.class
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
發現 他繼承了WebMvcConfigurationSupport,所以如上面所說因為繼承了WebMvcConfigurationSupport,相當於容器中已經有了WebMvcConfigurationSupport,所以預設配置都不會生效,都得自己在配置檔案中配置。