一、相关文档查看
近日阅读了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帮助我们进行定制配置