springboot的MVC配置原理
springboot現在是實現了mvc的自動配置,但是如果要修改/添加mvc的配置呢,比如上一篇的thymeleaf模板引擎,就自動配置了視圖解析器,添加了前綴:classpath:/templates/和后綴:.html 。這樣 訪問方法的映射路徑時,就不用添加文件的路徑和后綴名,但是如果訪問的文件不在 tmplates文件夾下或者是你想要訪問的文件后綴不是html,那么應該怎么重新修改mvc的配置呢?接下來進入官方文檔看mvc擴展/修改的說明,如下圖:

可以發現如果要擴展/修改 mvc配置 需要給自定義的mvc類添加 @Configuration注解 和 實現 WebMvcConfigurer接口,接下來用自定義視圖解析器例子說明.
默認的視圖解析器
springboot的自動裝配的視圖解析器是通過ContentNegotiatingViewResolver類(上圖的第一個)來實現的,如果要自定義視圖解析器,就得進入這個類去了解,如下圖:

可以發現該類實現了ViewResolver接口,一般實現了視圖解析器接口的類,都可以把它看作視圖解析器,所以想要自定義視圖解析器就需要實現該接口。ContentNegotiatingViewResolver類是springboot自動裝配的視圖解析器,而且該類實現視圖解析器的接口,所以關鍵是視圖解析器的接口,所以進入到ViewResolver接口可以發現里面包含一個resolveViewName()方法,該方法的作用是解析視圖。接下來返回ContentNegotiatingViewResolver類中查看是怎么重寫resolveViewName()方法的,如下圖:

核心是紅框部分,getCandidateViews()方法是獲取所有的候選視圖,該方法里面是循環所有的視圖解析器,然后通過視圖解析器去獲取所有視圖並添加到視圖候選區;getBestView()是從候選區中獲取最好的視圖,最后返回最好的視圖,接下來實現自定義視圖解析器。
自定義視圖解析器
首先在自己創建的mvc配置類里面創建一個靜態類去實現視圖解析器的ViewResolver接口,然后重寫里面的方法,如下:
/**
* 擴展mvc,如果你想要diy一些定制化的功能,只要寫這個組件,然后將它交給springboot,springboot會自動幫我們裝配。
*/
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//把視圖解析器放入ioc容器中才會生效
@Bean
public ViewResolver myViewResolve(){
return new MyViewResolve();
}
//自定義一個自己的視圖解析器,並重寫里面的方法
public static class MyViewResolve implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
然后測試一下,自己自定義的視圖解析器是否生效了,如下:
所有請求都會經過DispatcherServlet類的doDispatch()方法,所以在doDispatch()打斷點,如下圖:

可以發現是可以識別到自定義的視圖解析器。
springboot的MVC擴展
要想擴展mvc,根據官方文檔說明,如下圖:

擴展mvc的配置類,必須實現WebMvcConfigurer接口和添加@Configuration注解 ,但是不能添加@EnableWebMvc注解,因為添加該注解會讓springboot的mvc自動配置失效,如下:

上圖是springmvc自動配置的類,上面紅框部分是一個條件,如果該WebMvcConfigurationSupport類不存在則當前自動配置生效,這個類和@EnableWebMvc注解有聯系的,進入到@EnableWebMvc注解里面,如下:

該注解導入了一個類,在進入到該類,如下:

可以發現該類繼承了WebMvcConfigurationSupport類,所以所以添加了@EnableWebMvc注解就相當於添加了WebMvcConfigurationSupport類,而mvc自動配置的類啟動條件@ConditionalOnMissingBean中,是規定不能存在WebMvcConfigurationSupport類,存在則webMvc自動配置類失效。
所以官網 強調 自定義擴展mvc,不能添加@EnableWebMvc注解。
上面的自定義視圖解析器就是mvc擴展的一個例子,接下來在使用一個例子說明,mvc是如何擴展的,如下:
/**
* 擴展mvc
*/
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//視圖跳轉
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//返回/abc會跳轉到test.html
registry.addViewController("/abc").setViewName("test");
}
}
訪問結果如下:

訪問abc映射路徑,只有測試兩字,而訪問原來的test映射路徑,多了一些值,是因為,該test映射路徑里面添加了值。
該擴展是一個視圖跳轉,通常默認是瀏覽器訪問是訪問controller層的映射,但是這里添加了額外的映射,訪問/abc會映射test.html視圖。
總結
自定義配置類,必須實現WebMvcConfigurer接口和添加@Configuration注解 和屬性類xxProperties,並且配置類要添加一些配置類的啟動條件@ConditionalXX 和添加@EnableConfigurationProperties注解啟動對應的屬性類xxProperties。
