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類被棄用的嚴重警告。本次技術分享到這裡就結束了,感謝你耐心的閱讀。如果你在遇到同樣問題時還有更好的解決方案,可以在下方的評論區給我留言。