1. 程式人生 > 實用技巧 >Springboot 對 Springmvc 的擴充套件

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 的配置)