WebMvcConfigurerAdapter類被棄用後的兩種選擇

羅摩爾發表於2019-04-17

1. 介紹

在本文中,將介紹將spring 4.xx(或者更低)版本升級到Spring 5.xx以及將Spring Boot 1.xx版本升級到Spring Boot 2.xx版本後會報的一個嚴重警告:"Warning:The type WebMvcConfigurerAdapter is deprecated." ,以及快速的分析產生這個嚴重警告的原因和處理辦法。

2. 出現警告的原因

如果我們使用Spring 5.xx(或者Spring Boot 2.xx)版本來構建或者升級應用程式,在配置WebMvc時,則會出現此警告,這是因為在早期的Spring版本中,如果要配置Web應用程式,可以通過擴充套件WebMvcConfigurerAdapter類快熟實現配置,大致程式碼如下:

package com.ramostear.page;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * Spring 4(或者Spring Boot 1.x)版本配置Web應用程式示例
 * @author ramostear
 * @create-time 2019/4/18 0018-1:38
 */
@Configuration
public class OldMvcConfig extends WebMvcConfigurerAdapter{

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
        configurer.setUseSuffixPatternMatch(false);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/META-INF/resources/")
                .addResourceLocations("classpath:/public/")
                .addResourceLocations("classpath:/resources/");
        super.addResourceHandlers(registry);
    }
}

複製程式碼

WebMvcConfigurerAdapter 是一個實現了WebMvcConfigurer 介面的抽象類,並提供了全部方法的空實現,我們可以在其子類中覆蓋這些方法,以實現我們自己的配置,如檢視解析器,攔截器和跨域支援等...,由於Java的版本更新,在Java 8中,可以使用default關鍵詞為介面新增預設的方法,Spring在升級的過程中也同步支援了Java 8中這一新特性。下面是在Java 8 中給介面定義一個預設方法的簡單實現:

public interface MyInterface{
    
    default void sayHello(){
        //...
    }
    
    void sayName(){}
    
    String writeName(){}
    
    //...
}
複製程式碼

3. 解決方案

如前面所述,從Spring 5開始,WebMvcConfigure介面包含了WebMvcConfigurerAdapter類中所有方法的預設實現,因此WebMvcConfigurerAdapter這個介面卡就被打入冷宮了,下面是WebMvcConfigurerAdapter類部分原始碼示例:

/**
 * An implementation of {@link WebMvcConfigurer} with empty methods allowing
 * subclasses to override only the methods they're interested in.
 *
 * @author Rossen Stoyanchev
 * @since 3.1
 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
 * possible by a Java 8 baseline) and can be implemented directly without the
 * need for this adapter
 */
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {

	/**
	 * {@inheritDoc}
	 * <p>This implementation is empty.
	 */
	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
	}

	/**
	 * {@inheritDoc}
	 * <p>This implementation is empty.
	 */
	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	}
    
    ...
}        
複製程式碼

趣味提示:我們可以通過實現WebMvcConfigure介面中的方法來配置Web應用程式,而不需要讓WebMvcConfigurerAdapter這個中間商 賺差價。

如此這般,我們找到了一個消除警告的方法:直接實現WebMvcConfigurer介面。在我們準備與WebMvcConfigurer打交道之前,先看看此介面的基本情況:

public interface WebMvcConfigurer {

	default void configurePathMatch(PathMatchConfigurer configurer) {
	}

	/**
	 * Configure content negotiation options.
	 */
	default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
	}

	/**
	 * Configure asynchronous request handling options.
	 */
	default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
	}
    
   ...
}       
複製程式碼

現在,我們就可以動手配置Web應用程式了,大致的程式碼如下:

/**
 * Spring 5 (或者Spring Boot 2.x)版本配置Web應用程式示例
 * @author ramostear
 * @create-time 2019/4/18 0018-1:40
 */
@Configuration
public class MvcConfigure implements WebMvcConfigurer{

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.setUseSuffixPatternMatch(false);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/public/")
                .addResourceLocations("classpath:/resources/");
    }
}
複製程式碼

就這樣簡單地將警告消除了,將原來的繼承WebMvcConfigurerAdapter類改為實現WebMvcConfigurer介面,其餘的地方都沒有變化。但有一點需要注意,如果你是升級舊有的應用程式,需要將方法中對super()的呼叫程式碼清除。

至此,我們的程式又可以愉快的玩耍了。那麼,除了消除中間商 賺差價的方式來規避警告外,還有沒有其他的途徑呢?答案當然是肯定的。我們除了消除中間商從WebMvcConfigurer中獲得配置Web應用程式的途徑外,還可以直接從WebMvcConfigurationSupport這個配置“供應商“的手中獲取配置途徑。WebMvcConfigurationSupport是一個提供了以Java程式設計方式來配置Web應用程式的配置主類,所以我們可以從這個配置供應商的手中獲取Web應用程式的配置方式。方法很簡單,只需要擴充套件此類並重寫對應的方法即可。和上面的方式一樣,我們先看看此類的內部大致結構:

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
	...
    /**
	 * Provide access to the shared handler interceptors used to configure
	 * {@link HandlerMapping} instances with.
	 * <p>This method cannot be overridden; use {@link #addInterceptors} instead.
	 */
	protected final Object[] getInterceptors() {
		...
	}
    
    /**
	 * Return a handler mapping ordered at Integer.MAX_VALUE-1 with mapped
	 * resource handlers. To configure resource handling, override
	 * {@link #addResourceHandlers}.
	 */
	@Bean
	@Nullable
	public HandlerMapping resourceHandlerMapping() {
		...
		handlerMapping.setPathMatcher(mvcPathMatcher());
		handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
		handlerMapping.setInterceptors(getInterceptors());
		handlerMapping.setCorsConfigurations(getCorsConfigurations());
		return handlerMapping;
	}
}    
複製程式碼

是不是看到很熟悉的東西,有攔截器,靜態資源對映等等...,現在我們只需要擴充套件此類並重寫其中的方法,就可以配置我們的Web應用程式(還需要使用@Configuration對擴充套件類進行註釋),示例程式碼如下:

/**
 * 消除警告的第二種配置選擇
 * @author ramostear
 * @create-time 2019/4/7 0007-4:10
 */
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
        configurer.setUseSuffixPatternMatch(false);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("classpath:/META-INF/resources/")
                .addResourceLocations("classpath:/public/")
                .addResourceLocations("classpath:/resources/");
        super.addResourceHandlers(registry);
    }
}
複製程式碼

4. 結束語

在本文中,通過快速的梳理,給出了兩種不同的方案來消除由於升級Spring(或者Spring Boot)版本所帶來的WebMvcConfigurerAdapter類被棄用的嚴重警告。本次技術分享到這裡就結束了,感謝你耐心的閱讀。如果你在遇到同樣問題時還有更好的解決方案,可以在下方的評論區給我留言。

原文作者:譚朝紅
原文標題:WEBMVCCONFIGURERADAPTER被棄用後的兩個選擇

原文連結:www.ramostear.com/articles/af…

相關文章