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執行過程
相關文章
- Springboot MVC 自動配置Spring BootMVC
- SpringBoot——自定義自動配置與起步依賴Spring Boot
- SpringBoot自動裝配-自定義StartSpring Boot
- Springboot實現基於字首的自定義配置和自動提示功能Spring Boot
- _008_SpringBoot_自定義配置Spring Boot
- 自定義檢視指令
- 全網最深分析SpringBoot MVC自動配置失效的原因Spring BootMVC
- Laravel 自定義檢視元件Laravel元件
- 自定義springboot啟動器Spring Boot
- springboot如何使用自定義配置檔案Spring Boot
- SpringBoot讀取自定義配置檔案Spring Boot
- 【Spring Boot 使用記錄】kafka自動配置和自定義配置Spring BootKafka
- samba 基本配置及自定義控制Samba
- springboot 自動配置原理Spring Boot
- SpringBoot自動配置原理Spring Boot
- SpringBoot的自動配置Spring Boot
- SpringBoot(03)——自動配置Spring Boot
- SpringBoot | 自動配置原理Spring Boot
- SpringBoot(二)自動配置Spring Boot
- 自定義 Command 檢視 Laravel 日誌Laravel
- springboot+redis+Interceptor+自定義annotation實現介面自動冪等Spring BootRedis
- Springboot快速上手- 第四篇 自定義配置Spring Boot
- springboot讀取自定義配置檔案節點Spring Boot
- 【asp.net core 系列】3 檢視以及檢視與控制器ASP.NET
- 自定義檢視---圓角柱狀圖(一)
- springboot 自動配置案例分析Spring Boot
- SpringBoot的自動配置原理Spring Boot
- springboot_自動配置原理Spring Boot
- SpringBoot自定義StarterSpring Boot
- springboot 自定義errorSpring BootError
- SpringBoot 自定義 starterSpring Boot
- SpringBoot原理深入及原始碼剖析(一) 依賴管理及自動配置Spring Boot原始碼
- Spring Boot 自動配置的原理、核心註解以及利用自動配置實現了自定義 Starter 元件Spring Boot元件
- 檢視控制器
- Asp.Net MVC控制器獲取檢視傳值幾種方式ASP.NETMVC
- springboot web專案建立及自動配置分析(thymeleaf+flyway)Spring BootWeb
- Linux下檢視、新增及配置Linux
- SpringBoot入門(二):日誌及自定義屬性Spring Boot