SpringBoot(3)-MVC自動配置及自定義檢視控制器
1. 主要類:
WebMvcAutoConfiguration: MVC的自動配置類
EnableWebMvcConfiguration: 啟用WebMvcConfiguration的類
DelegatingWebMvcConfiguration: WebMvcConfiguration委託的代理類
WebMvcConfigurerComposite: “具體WebMvcConfiguration的委託類”
`
WebMvcAutoConfigurationAdapter: MVC自動配置介面卡,其實現了WebMvcConfiguration
WebMvcConfigurer: MVC配置介面
WebMvcConfigurerAdapter: MVC配置介面卡(1.8後棄用,因為介面支援default預設實現)
2. 檢視解析器初始化:
springboot啟動後會自動配置mvc的元件,即WebMvcAutoConfiguration,自動進行mvc的一些配置
其內部靜態類WebMvcAutoConfigurationAdapter也是一個元件,通過@Import匯入EnableWebMvcConfiguration元件
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
EnableWebMvcConfiguration繼承了DelegatingWebMvcConfiguration委託代理類
@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
代理類通過setConfigurers方法來初始化mvc配置的具體委託類
@Autowired會從容器總把實現WebMvcConfigurer介面的類都注入到configurers
然後將所有的mvc配置類新增到WebMvcConfigurerComposite
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
//也實現了WebMvcConfigurer當並沒有@Configuration到容器中
class WebMvcConfigurerComposite implements WebMvcConfigurer {
private final List<WebMvcConfigurer> delegates = new ArrayList<>();
public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.delegates.addAll(configurers);
}
}
dubug可以知道,預設使用WebMvcAutoConfigurationAdapter
所以,要想自定義mvc的配置,只需要實現WebMvcConfigurer介面,並將該類放入容器中即可
@Configuration
public class MyConfigure implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/testView").setViewName("success");
}
}
3. MVC檢視功能配置:
由上可知,mvc的配置,預設使用WebMvcAutoConfigurationAdapter來配置
這個類在配置的時候,會往容器中新增三個檢視bean,主要關注ContentNegotiatingViewResolver注意其該配置resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);設定最高階的Order,後續會提到
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
... ... ...
@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix(this.mvcProperties.getView().getPrefix());
resolver.setSuffix(this.mvcProperties.getView().getSuffix());
return resolver;
}
@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
return resolver;
}
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver uses all the other view resolvers to locate
// a view so it should have a high precedence
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
... ... ...
ContentNegotiatingViewResolver這個檢視解析器主要是用來組合所有檢視解析器的
在其內部實現方法initServletContext可以看到,將所有檢視解析器(除本類)新增到本類的中viewResolvers
可見,想要自定義檢視解析器,可以實現ViewResolver介面,然後加入容器即可,本文不論述
4. MVC解析檢視過程:
前端控制器(DispatcherServlet),在第一次呼叫檢視解析器之前,會通過initViewResolvers方法先初始化檢視解析器
該方法中,獲取容器內所有檢視解析器,即容器中實現ViewResolver介面的類
然後所有檢視解析器根據Order排序,上文提及ContentNegotiatingViewResolver設定了最高階別Order,所以它會排在第一個
當初始化檢視解析器後,前端控制器通過resolveViewName方法遍歷所有檢視解析器來解析,能解析立即返回View
ContentNegotiatingViewResolver排在第一個,所以會最先呼叫
其內部方法通過getCandidateViews來解析出所有檢視,最後處理返回一個bestView給前端控制器
在getCandidateViews方法中,this.viewResolvers就是之前ContentNegotiatingViewResolver組合的所有檢視解析器
呼叫各檢視解析器的實現方法resolveViewName來解析檢視
有興趣的可以研究一些這個方法,我就算了
詳細的MVC執行過程可參考:SpringBoot(2)-MVC執行過程
相關文章
- MVC自定義檢視規則MVC
- Springboot MVC 自動配置Spring BootMVC
- SpringBoot——自定義自動配置與起步依賴Spring Boot
- 自定義MVC檢視引擎ViewEngine 建立Model的專屬檢視MVCView
- SpringBoot自動裝配-自定義StartSpring Boot
- 自定義檢視指令
- Springboot實現基於字首的自定義配置和自動提示功能Spring Boot
- Laravel 自定義檢視元件Laravel元件
- 自定義例外 + 建立檢視
- 自定義提醒檢視Alert-動態繪製
- 全網最深分析SpringBoot MVC自動配置失效的原因Spring BootMVC
- _008_SpringBoot_自定義配置Spring Boot
- 為什麼前端模型-檢視-控制器MVC會死?前端模型MVC
- 【Spring Boot 使用記錄】kafka自動配置和自定義配置Spring BootKafka
- samba 基本配置及自定義控制Samba
- 自定義springboot啟動器Spring Boot
- Spring自定義MVCSpringMVC
- Xamarin iOS教程之自定義檢視iOS
- SpringBoot讀取自定義配置檔案Spring Boot
- springboot如何使用自定義配置檔案Spring Boot
- 【asp.net core 系列】3 檢視以及檢視與控制器ASP.NET
- 自定義 Command 檢視 Laravel 日誌Laravel
- 自定義檢視---圓角柱狀圖(一)
- SpringBoot | 自動配置原理Spring Boot
- SpringBoot的自動配置Spring Boot
- SpringBoot(03)——自動配置Spring Boot
- SpringBoot(二)自動配置Spring Boot
- SpringBoot自動配置原理Spring Boot
- springboot 自動配置原理Spring Boot
- springboot+redis+Interceptor+自定義annotation實現介面自動冪等Spring BootRedis
- [譯] 通過檢視控制器容器和子檢視控制器避免龐大的檢視控制器
- Spring Boot 自動配置的原理、核心註解以及利用自動配置實現了自定義 Starter 元件Spring Boot元件
- 自定義Toast及視窗透明處理AST
- Asp.Net MVC控制器獲取檢視傳值幾種方式ASP.NETMVC
- AlertDialog 自定義對話方塊檢視
- 如何使用Android自定義複合檢視Android
- 前臺使用者自定義效能檢視
- Springboot快速上手- 第四篇 自定義配置Spring Boot