一、相關文檔查看
近日閱讀了SpringMVC自動配置的源碼,總結一下
二、理解解析
以下是Spring Boot對Spring MVC的默認配置(WebMvcAutoConfiguration)
配置文件的位置 ~ 在Spring Boot原理哪一篇知道,Spring Boot對很多框架的支持配置文件命名爲: xxxAutoConfiguration
1、包含了ContentNegotiatingViewResolver
和 BeanNameViewResolver
1.1 ContentNegotiatingViewResolver
自動轉配了該類,查看ContentNegotiatingViewResolver
【總結來說】自動配置了ViewResolver(視圖解析器),視圖解析器就是根據方法的返回值得到視圖對象View,視圖對象將決定如何渲染...
ContentNegotiatingViewResolver 組合了所有的視圖
那麼問題來了,我們如何定義我們自己的視圖呢?自動將其組合進來
1)寫一個類實現ViewResolver接口,然後實現裏面的resolveViewName方法
2)生成改Bean,交給Spring管理
@Component
public class TestViewResolver implements ViewResolver {
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
重新啓動項目
【再次總結】
1、Spring Boot在自動配置很多組件的時候,先看容器有沒有用戶配置的(@Bean/@Component),如果有,就用用戶自己配置的,如果沒有,才自動配置。
但是有些組件可以有多個,例如ViewResolver將用戶的配置和自己的默認組合起來
1.2 BeanNameViewResolver
解析器試圖將返回的名稱當作視圖bean的name
2、靜態資源文件夾路徑 webjars
對公共靜態資源的訪問時,支持使用webjar去訪問到jaj包裏面的靜態文件,例如
1)在Pom文件中引入jq.jar
<!--引入jQuery-webjar-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.1.1</version>
</dependency>
2) 項目啓動之後,訪問:
http://localhost:8081/webjars/jquery/3.1.1/jquery.js
3、自動註冊了Converter、GenericConverter、formatter beans
converter: 轉化器,類型轉化使用Converter
Formatter: 格式轉化器, 2020.06.03 ===》 Date
以Formatter分析
查看this.mvcProperties
【總結兩個點】
1)默認情況下,使用/來解析日期
2)如果想要自己添加格式化轉化器,我們只需要放在容器中即可。
3)自定義自己的日期轉化器
@Component
public class MyDateConverter implements Converter<String, Date> {
private String dataPattern = "yyyy-MM-dd";
@Override
public Date convert(String s) {
Date date = null;
try {
date = new SimpleDateFormat(dataPattern).parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
4)重新啓動項目
【注意】日期格式化只能支持一種,此時如果使用:1995/08/10則報錯
4、支持HttpMessageConverters
SpringMvc用來轉化Http請求和響應, User-- JSON
HttpMessageConverters是從容器中確定的,獲取所有的httpMessageConverter
那麼如何給容器中添加HttpMessageConverter,只需要將自己的組件註冊進容器中即可
5、定義錯誤代碼生成規則 MessageCodesResolver
目錄
1、包含了ContentNegotiatingViewResolver 和 BeanNameViewResolver
3、自動註冊了Converter、GenericConverter、formatter beans
5、定義錯誤代碼生成規則 MessageCodesResolver
8、配置默認的ConfigurableWebBindingInitializer 來替換默認的
6、 靜態首頁資源配置
將"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
四個位置存在的index.html當做首頁,如果不存在則報錯。並且優先級由高到底
7、默認的圖標
因此,只需要將圖標放在靜態資源路徑下,命名爲:favicon.ico,則可以更換圖標
8、配置默認的ConfigurableWebBindingInitializer
來替換默認的
三、添加額外的MVC配置
如果想要保持原來的自動配置不變,增加自己的配置,則可以
1)添加一個類使用@Configuration
2)繼承WebMvcConfigurerAdapter
package com.dgut.edu.cn.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
private String dataPattern = "yyyy=MM=dd";
public MyMvcConfig() {
super();
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
super.configurePathMatch(configurer);
}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
super.configureContentNegotiation(configurer);
}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
super.configureAsyncSupport(configurer);
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
super.configureDefaultServletHandling(configurer);
}
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new Formatter<Date>() {
@Override
public String print(Date date, Locale locale) {
return Long.valueOf(date.getTime()).toString();
}
@Override
public Date parse(String s, Locale locale) throws ParseException {
Date date = null;
try {
date = new SimpleDateFormat(dataPattern).parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
});
super.addFormatters(registry);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
}
@Override
public void addCorsMappings(CorsRegistry registry) {
super.addCorsMappings(registry);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//super.addViewControllers(registry);
registry.addViewController("/atguigu").setViewName("success");
}
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
super.configureViewResolvers(registry);
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
super.addArgumentResolvers(argumentResolvers);
}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
super.addReturnValueHandlers(returnValueHandlers);
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
super.extendMessageConverters(converters);
}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
super.configureHandlerExceptionResolvers(exceptionResolvers);
}
@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
super.extendHandlerExceptionResolvers(exceptionResolvers);
}
@Override
public Validator getValidator() {
return super.getValidator();
}
@Override
public MessageCodesResolver getMessageCodesResolver() {
return super.getMessageCodesResolver();
}
}
此時,新增加的視圖映射也會實現
原理
1)WebMvcAutoConfiguration是SpringMVC的自動配置類
2)在做其他自動配置時會導入;@Import(EnableWebMvcConfiguration.class)
由於:WebMvcConfigureAdapter 實現WebMvcConfigurer,因此我們的類也會被加載
3)容器中所有的WebMvcConfigurer都會一起起作用
4)我們的配置類也會被調用;
【總結】
SpringMVC的自動配置和我們的擴展配置都會起作用
四、全面接管SpringMVC
我們需要在配置類中添加@EnableWebMvc
因此全面交由自己管理SpringMvc,但是在項目中不推薦使用
原理:
爲什麼增加了該註解,自動配置就失效了呢?
1、查看該註解
使用該註解時,導入了
DelegatingWebMvcConfiguration.class
2、查看SpringMvc生效的條件
五、如何修改SpringBoot的默認配置
模式:
1)、SpringBoot在自動配置很多組件的時候,先看容器中有沒有用戶自己配置的(@Bean、@Component)如
果有就用用戶配置的,如果沒有,才自動配置;如果有些組件可以有多個(ViewResolver)將用戶配置的和自己默
認的組合起來;
2)、在SpringBoot中會有非常多的xxxConfigurer幫助我們進行擴展配置
3)、在SpringBoot中會有很多的xxxCustomizer幫助我們進行定製配置