springboot运行原理:https://blog.csdn.net/gdnlnsjd/article/details/121439543
springboot自动装配原理:https://blog.csdn.net/gdnlnsjd/article/details/121441166
我们已经了解了springboot的运行原理和自动装配原理,我们还需要知道一个东西,就是SpringBoot对我们的SpringMVC还做了哪些配置,包括如何扩展,如何定制。
我们从源码和官方文档去分析
官方文档
我们从官方文档中得到下面的解析:
Spring MVC Auto-configuration
// Spring Boot为Spring MVC提供了自动配置,它可以很好地与大多数应用程序一起工作。
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
// 自动配置在Spring默认设置的基础上添加了以下功能:
The auto-configuration adds the following features on top of Spring’s defaults:
// 包含视图解析器
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
// 支持静态资源文件夹的路径,以及webjars
Support for serving static resources, including support for WebJars
// 自动注册了Converter:
// 转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
// Formatter:【格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象】
Automatic registration of Converter, GenericConverter, and Formatter beans.
// HttpMessageConverters
// SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串,可以去看官网文档解释;
Support for HttpMessageConverters (covered later in this document).
// 定义错误代码生成规则的
Automatic registration of MessageCodesResolver (covered later in this document).
// 首页定制
Static index.html support.
// 图标定制
Custom Favicon support (covered later in this document).
// 初始化数据绑定器:帮我们把请求数据绑定到JavaBean中!
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己
的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供
RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义
实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
*/
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration
(interceptors, formatters, view controllers, and other features), you can add your own
@Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide
custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or
ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
// 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.
我们来仔细对照,看一下它怎么实现的,它告诉我们SpringBoot已经帮我们自动配置好了SpringMVC,然后自动配置了哪些东西呢?
自动配置了ViewResolver,就是我们之前学习的SpringMVC的视图解析器;
即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。
我们去看看这里的源码:我们找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver。找到如下方法!
我们点到ContentNegotiatingViewResolver中看看这个类
我们发现它实现了ViewResolver接口,实现了ViewResolver接口的类,我们就可以将其看作视图解析器。
我们再进入这个接口中
我们发现这个接口中就一个resolveViewName()方法,我们看看ContentNegotiatingViewResolver是如何重写这个方法的
// getCandidateViews():获取候选的视图对象
//getBestView():选择一个最适合的视图对象,然后把这个对象返回
点进getCandidateViews()看看:
我们可以看到他是把所有的视图解析器拿来,进for循环,挨个解析,然后将所有候选视图返回
所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
我们再去研究下他的组合逻辑,看到for循环中遍历的属性viewResolvers,看看它是在哪里进行赋值的!
// 这里它是从beanFactory工具中获取容器中的所有视图解析器
既然它是在容器中去找视图解析器,我们是否可以猜想,我们就可以去实现一个视图解析器了呢?
我们可以自己给容器中去添加一个视图解析器;这个类就会帮我们自动的将它组合进来;我们去实现一下
1、我们在我们的主程序中去写一个视图解析器来试试;
2、怎么看我们自己写的视图解析器有没有起作用呢?
我们给 DispatcherServlet 中的 doDispatch方法 加个断点进行调试一下,因为所有的请求都会走到这个方法中
发现我们自己写的视图解析器确实生效了
所以说,我们如果想要使用自己定制化的东西,我们只需要给容器中添加这个组件就好了!剩下的事情SpringBoot就会帮我们做了!
我们再看看我们还能自己定制些什么
转换器和格式化器
找到格式化转换器,我们看看其中时间的格式转换:
点进去:
发现这个属性存在于WebMvcProperties类中,所以我们可以对其进行自定义配置
其余的就不一一举例了,大家可以下去多研究探讨即可!
扩展使用SpringMVC 官方文档如下:
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.
如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供RequestMappingHandlerMappingRequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解;我们去自己写一个;我们新建一个包叫config,写一个类MyMvcConfig,再添加一个addViewControllers()试试;
我们去浏览器访问一下:
确实也跳转过来了!所以说,我们要扩展SpringMVC,官方就推荐我们这么去使用(即自己写一个实现webmvcconfiguer接口的类,既保SpringBoot留所有的自动配置,也能用我们扩展的配置!
我们可以去分析一下原理:
1、WebMvcAutoConfiguration 是 SpringMVC的自动配置类,里面有一个类WebMvcAutoConfigurationAdapter
2、这个类上有一个注解,在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class)
3、我们点进EnableWebMvcConfiguration这个类看一下,它继承了一个父类:DelegatingWebMvcConfiguration
这个父类中有这样一段代码:
即从IOC容器中获取所有的webmvcConfigurer(包括我们自定义的实现了webmvcConfigurer接口的自定义类),组合到WebMvcConfigurerComposite中
我们可以在这个类中去寻找一个我们刚才自定义类中重写的addViewControllers当做参考,发现它调用了一个
点进去
所以得出结论:所有的WebMvcConfiguration都会被作用,不止Spring自带的配置类,我们自己的配置类当然也会被调用;
那为什么不能加@EnableWebMvc呢?因为加了之后默认的mvc自动配置类就会失效,由我们自定义的类完全控制Spring MVC
点进@EnableWebMvc看看
发现它导入了一个DelegatingWebMvcConfiguration类,而这个类继承了WebMvcConfigurationSupport类
我们再看看WebMvcAutoConfiguration自动配置类生效的条件
所以如果我们使用了@EnableWebMvc,Ioc容器中就存在了WebMvcConfigurationSupport类,默认的mvc自动配置类就会失效,由我们自定义的类完全控制Spring MVC
但是建议不要这样去做,还是在保留默认配置的情况下,新添WebMvcConfiguration即可(即自定义一个配置类实现WebMvcConfiguration接口,然后在里面添加自定义的配置)。