1. 程式人生 > >SpringBoot2.x中WebMvcConfigurerAdapter已過時,使用WebMvcConfigurationSupport替換時自動配置失效

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,所以預設配置都不會生效,都得自己在配置檔案中配置。