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