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,所以默认配置都不会生效,都得自己在配置文件中配置。

猜你喜欢

转载自blog.csdn.net/szzzgyn/article/details/85622112
今日推荐