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。