Springboot 對 Springmvc 的擴充套件
我們檢視 Springboot 官方文件,裡面有關於對 Springmvc 的擴充套件介紹
後面這段話的意思是: 如果你想保留 Spring Boot MVC 的功能,並且你希望新增其它的 MVC 配置(攔截器、格式化器、檢視控制器、和其它的功能),你可以新增自己的 @Configuration 配置類,並且讓該配置類實現 WebMvcConfigurer 介面,但是不要在該配置類上新增 @EnableWebMvc 註解,如果你想要 RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExeceptionHandlerExceptionResolver 的定製例項,可以宣告一個 WebMvcRegistrationsAdapter 例項來提供上面這些元件.
如果你想全面接管 Spring MVC ,那麼你可以新增帶有 @EnableWebMvc、@Configuration 註解的配置類
關於 @EnableWebMvc 註解的作用,可以參考一下這篇部落格https://www.cnblogs.com/xiaomaomao/p/13998924.html
按照上面的提示,建立一個配置類並實現 WebMvcConfigurer 介面(當然也可以繼承 WebMvcConfigurerAdapter 這個抽象類,其實是同一個意思,因為WebMvcConfigurerAdapter 也是 WebMvcConfigurer 的實現類)
/** * 1、這裡我們可以實現 WebMvcConfigurer 介面,並重寫其中的方法來完成 springmvc 的擴充套件功能 * 2、也可以繼承 WebMvcConfigurerAdapter 抽象類,其實 WebMvcConfigurerAdapter 也是實現了 * WebMvcConfigurer 介面 */ @Configuration public class MyWebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { // 瀏覽器訪問 localhost:8080/ 時,會跳轉到檢視 resources/templates/success.html 頁面 registry.addViewController("/xiaomao").setViewName("xiaomao/success"); // 瀏覽器訪問 localhost:8080/xiaomaomao 時,會跳轉到檢視 resources/templates/success.html 頁面 registry.addViewController("/xiaomaomao").setViewName("xiaomao/success"); } }
原理:
我們都知道 springboot 對 springmvc 的自動配置相關資訊都在 WebMvcConfiguration 這個類裡面,點進去這個類可以看到裡面有一個靜態內部類WebMvcAutoConfigurationAdapter
// 標記這是一個配置類 @Configuration // 如果當前是 web 應用 @ConditionalOnWebApplication // 如果存在 Servlet、DispatcherServlet、WebMvcConfigurerAdapter 這些類 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class,WebMvcConfigurerAdapter.class }) // 如果應用中不存在 WebMvcConfigurationSupport 這個類 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) // 自動配置順序 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class }) // springboot 對於 springmvc 的自動配置都在這個類裡面 public class WebMvcAutoConfiguration { ... @Configuration @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) // WebMvcAutoConfigurationAdapter 是 WebMvcAutoConfiguration 的靜態內部類 // 它繼承了 WebMvcConfigurerAdapter 這個抽象類,看到這個類是不是有點熟悉,我們對 springmvc 進行擴充套件的 // 時候也是繼承的這個類 public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter { ... } }
那麼WebMvcAutoConfigurationAdapter 這個配置類起作用的應該是@Import(EnableWebMvcConfiguration.class),點進去EnableWebMvcConfiguration 這個類看一下
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
private final WebMvcProperties mvcProperties;
private final ListableBeanFactory beanFactory;
private final WebMvcRegistrations mvcRegistrations;
...
}
發現這個類繼承了DelegatingWebMvcConfiguration ,繼續點進去看
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
// WebMvc 配置綜合類
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
// 方法上使用 @Atuowired 註解,如果該方法有引數,那麼引數會從 IOC 容器中去取
@Autowired(required = false)
// 那麼容器中所有的 WebMvcConfigurer 都會賦值給 configurers 這個引數
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
// 呼叫 WebMvcConfigurerComposite 的 addWebMvcConfigurers() 方法
this.configurers.addWebMvcConfigurers(configurers);
}
}
點進去addWebMvcConfigurers(List<WebMvcConfigurer configurers) 方法進行檢視
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<WebMvcConfigurer>();
public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
// 將 IOC 容器中所有的 WebMvcConfigurer 都賦值給了 delegates 這個 List 集合
this.delegates.addAll(configurers);
}
}
}
我們可以在 DelegatingWebMvcConfiguration 類中去尋找一個我們剛才設定的 addViewControllers() 當做參考,發現它呼叫了 WebMvcConfigurerComposite 的addViewControllers()方法
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// delegates 就是我們從 IOC 容器中取出來的所有的 WebMvcConfigurer
for (WebMvcConfigurer delegate : this.delegates) {
// 對每個 WebMvcConfigurer 都執行 addViewControllers 操作
delegate.addViewControllers(registry);
}
}
這樣,所有的WebMvcConfigurer 都執行了addViewControllers 操作(包括我們自定義的和 springboot 預設對 mvc 的配置)