12、SpringBoot:MVC 自动配置原理
12.1、官网阅读
在进行项目编写前,我们还需要知道一个东西,就是 SpringBoot 对我们的 SpringMVC 还做了哪些配置,包括如何扩展,如何定制。
只有把这些都搞清楚了,我们在之后使用才会更加得心应手。途径一:源码分析,途径二:官方文档!
我们来仔细对照,看一下它怎么实现的,它告诉我们 SpringBoot 已经帮我们自动配置好了 SpringMVC,然后自动配置了哪些东西呢?
12.2、ContentNegotiatingViewResolver 内容协商视图解析器
自动配置了 ViewResolver,就是我们之前学习的 SpringMVC 的视图解析器;
即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。
我们去看看这里的源码:我们找到 WebMvcAutoConfiguration , 然后搜索 ContentNegotiatingViewResolver。找到如下方法!
我们可以点进这类看看!找到对应的解析视图的代码;
我们继续点进去看,他是怎么获得候选的视图的呢?
getCandidateViews 中看到他是把所有的视图解析器拿来,进行 while 循环,挨个解析!
所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
我们再去研究下他的组合逻辑,看到有个属性 viewResolvers,看看它是在哪里进行赋值的!
既然它是在容器中去找视图解析器,我们是否可以猜想,我们就可以去实现一个视图解析器了呢?
我们可以自己给容器中去添加一个视图解析器;这个类就会帮我们自动的将它组合进来;我们去实现一下
1、我们在我们的主程序中去写一个视图解析器来试试;
2、怎么看我们自己写的视图解析器有没有起作用呢?
我们给 DispatcherServlet 中的 doDispatch 方法 加个断点进行调试一下,因为所有的请求都会走到这个方法中
3、我们启动我们的项目,然后随便访问一个页面,看一下 Debug 信息;
找到 this
找到视图解析器,我们看到我们自己定义的就在这里了;
所以说,我们如果想要使用自己定制化的东西,我们只需要给容器中添加这个组件就好了!剩下的事情 SpringBoot 就会帮我们做了!
12.3、转换器和格式化器
找到格式化转换器:
点击去:
可以看到在我们的 Properties 文件中,我们可以进行自动配置它!
如果配置了自己的格式化方式,就会注册到 Bean 中生效,我们可以在配置文件中配置日期格式化的规则:
其余的就不一一举例了,大家可以下去多研究探讨即可!
12.4、修改 SpringBoot 的默认配置
这么多的自动配置,原理都是一样的,通过这个 WebMVC 的自动配置原理分析,我们要学会一种学习方式,通过源码探究,得出结论;这个结论一定是属于自己的,而且一通百通。
SpringBoot 的底层,大量用到了这些设计细节思想,所以,没事需要多阅读源码!得出结论;
SpringBoot 在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置 @bean),如果有就用用户配置的,如果没有就用自动配置的;
如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
扩展使用 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.
我们要做的就是编写一个 @Configuration 注解类,并且类型要为 WebMvcConfigurer,还不能标注 @EnableWebMvc 注解;我们去自己写一个;我们新建一个包叫 config,写一个类 MyMvcConfig;
我们去浏览器访问一下:
确实也跳转过来了!所以说,我们要扩展 SpringMVC,官方就推荐我们这么去使用,既保 SpringBoot 留所有的自动配置,也能用我们扩展的配置!
我们可以去分析一下原理:
1、WebMvcAutoConfiguration 是 SpringMVC 的自动配置类,里面有一个类 WebMvcAutoConfigurationAdapter
2、这个类上有一个注解,在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class)
3、我们点进 EnableWebMvcConfiguration 这个类看一下,它继承了一个父类:DelegatingWebMvcConfiguration
这个父类中有这样一段代码:
4、我们可以在这个类中去寻找一个我们刚才设置的 viewController 当做参考,发现它调用了一个
5、我们点进去看一下
所以得出结论:所有的 WebMvcConfiguration 都会被作用,不止 Spring 自己的配置类,我们自己的配置类当然也会被调用;
12.5、全面接管 SpringMVC
官方文档:
全面接管即:SpringBoot 对 SpringMVC 的自动配置不需要了,所有都是我们自己去配置!
只需在我们的配置类中要加一个 @EnableWebMvc。
我们看下如果我们全面接管了 SpringMVC 了,我们之前 SpringBoot 给我们配置的静态资源映射一定会无效,我们可以去测试一下;
不加注解之前,访问首页:
给配置类加上注解:@EnableWebMvc
我们发现所有的 SpringMVC 自动配置都失效了!回归到了最初的样子;
当然,我们开发中,不推荐使用全面接管 SpringMVC
思考问题?为什么加了一个注解,自动配置就失效了!我们看下源码:
1、这里发现它是导入了一个类,我们可以继续进去看
2、它继承了一个父类 WebMvcConfigurationSupport
3、我们来回顾一下 Webmvc 自动配置类
总结一句话:@EnableWebMvc 将 WebMvcConfigurationSupport 组件导入进来了;
而导入的 WebMvcConfigurationSupport 只是 SpringMVC 最基本的功能!
在 SpringBoot 中会有非常多的扩展配置,只要看见了这个,我们就应该多留心注意~