MVC配置原理-源码
在进行项目编写前,我们还需要知道一个东西,就是SpringBoot对我们的SpringMVC还做了哪些配置,包括如何扩展,如何定制。
途径一:源码分析
途径二:官方文档
举例
ContentNegotiatingViewResolver 内容协商视图解析器
自动配置了ViewResolver,就是我们之前学习的SpringMVC的视图解析器;
即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。
我们去看看这里的源码:我们找到 WebMvcAutoConfiguration , 然后搜索ContentNegotiatingViewResolver。找到如下方法!
@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使用所有其他视图解析器来定位视图,因此它应该具有较高的优先级
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
我们可以点进这类看看!找到对应的解析视图的代码;
@Nullable // 注解说明:@Nullable 即参数可为null
public View resolveViewName(String viewName, Locale locale) throws Exception {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
if (requestedMediaTypes != null) {
// 获取候选的视图对象
List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
// 选择一个最适合的视图对象,然后把这个对象返回
View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
if (bestView != null) {
return bestView;
}
}
// .....
}
我们继续点进去看,他是怎么获得候选的视图的呢?
getCandidateViews中看到他是把所有的视图解析器拿来,进行while循环,挨个解析!
Iterator var5 = this.viewResolvers.iterator();
所以得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
我们再去研究下他的组合逻辑,看到有个属性viewResolvers,看看它是在哪里进行赋值的!
protected void initServletContext(ServletContext servletContext) {
// 这里它是从beanFactory工具中获取容器中的所有视图解析器
// ViewRescolver.class 把所有的视图解析器来组合的
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
ViewResolver viewResolver;
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList(matchingBeans.size());
}
// ...............
}
既然它是在容器中去找视图解析器,我们是否可以猜想,我们就可以去实现一个视图解析器了呢?
我们可以自己给容器中去添加一个视图解析器;这个类就会帮我们自动的将它组合进来;我们去实现一下
详情请见:
修改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.
如果您想保留 Spring Boot MVC 功能并添加额外的 MVC 配置(拦截器、格式化程序、视图控制器和其他功能),您可以添加您自己的 WebMvcConfigurer 类型的 @Configuration 类,但不添加 @EnableWebMvc。 如果您希望提供 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 的自定义实例,您可以声明一个 WebMvcRegistrationsAdapter 实例来提供此类组件。
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,
还不能标注@EnableWebMvc注解;我们去自己写一个;我们新建一个包叫config,写一个类MyMvcConfig;
//应为类型要求为WebMvcConfigurer,所以我们实现其接口
//可以使用自定义类扩展MVC的功能
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 浏览器发送/test , 就会跳转到test页面;
registry.addViewController("/test").setViewName("test");
}
}
我们可以去分析一下原理:
1、WebMvcAutoConfiguration 是 SpringMVC的自动配置类,里面有一个类WebMvcAutoConfigurationAdapter
2、这个类上有一个注解,在做其他自动配置时会导入:@Import(EnableWebMvcConfiguration.class)
3、我们点进EnableWebMvcConfiguration这个类看一下,它继承了一个父类:DelegatingWebMvcConfiguration
这个父类中有这样一段代码:
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
// 从容器中获取所有的webmvcConfigurer
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
}
4、我们可以在这个类中去寻找一个我们刚才设置的viewController当做参考,发现它调用了一个
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
}
5、我们点进去看一下
public void addViewControllers(ViewControllerRegistry registry) {
Iterator var2 = this.delegates.iterator();
while(var2.hasNext()) {
// 将所有的WebMvcConfigurer相关配置来一起调用!包括我们自己配置的和Spring给我们配置的
WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
delegate.addViewControllers(registry);
}
}
所以得出结论:所有的WebMvcConfiguration都会被作用,不止Spring自己的配置类,我们自己的配置类当然也会被调用;
全面接管SpringMVC
官方文档:
If you want to take complete control of Spring MVCyou can add your own @Configuration annotated with @EnableWebMvc.
全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己去配置!
只需在我们的配置类中要加一个@EnableWebMvc。
参考链接
狂神说SpringBoot12:MVC自动配置原理 (qq.com)
MVC配置原理-源码的更多相关文章
- SharedPreferences 原理 源码 进程间通信 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 【陪你系列】5 千字长文+ 30 张图解 | 陪你手撕 STL 空间配置器源码
大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub https://github.com/rongweihe/MoreT ...
- MyEclipse如何配置Struts2源码的框架压缩包
1.MyEclipse如何配置Struts2源码的框架压缩包 如本机的Struts2框架压缩包路径为:D:\MyEclipseUserLibraries\struts\struts-2.3.15.3- ...
- Laya Timer原理 & 源码解析
Laya Timer原理 & 源码解析 @author ixenos 2019-03-18 16:26:38 一.原理 1.将所有Handler注册到池中 1.普通Handler在handle ...
- 深入理解Faiss 原理&源码 (一) 编译
目录 深入理解Faiss 原理&源码 (一) 编译 mac下安装 安装mac xcode工具包 安装 openblas 安装swig 安装libomp 编译faiss 附录 深入理解Faiss ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- spring IOC DI AOP MVC 事务, mybatis 源码解读
demo https://gitee.com/easybao/aop.git spring DI运行时序 AbstractApplicationContext类的 refresh()方法 1: pre ...
- spring MVC mybatis dispacherServlet(源码解读)
以下源码版本(4.2.0.RELEASE) dispacherServlet是servlet的实现类,是spring MVC的前端转发器,是spring MVC的核心. 那么它做了哪些事呢? 它主要做 ...
- CYQ.Data.Orm.DBFast 新增类介绍(含类的源码及新版本配置工具源码)
前言: 以下功能在国庆期就完成并提前发布了,但到今天才有时间写文介绍,主要是国庆后还是选择就职了,悲催的是上班的地方全公司都能上网,唯独开发部竟不让上网,是个局域网. 也不是全不能上,房间里有三台能上 ...
随机推荐
- php curl处理get和post请求
CURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 CURL 库.使用PHP的CURL 库可以简单和有效地去抓网页.你只 ...
- 流媒体传输协议(rtp/rtcp/rtsp/rtmp/mms/hls)转
常用的流媒体协议主要有HTTP渐进下载和基于RTSP/RTP的实时流媒体协议两类.在流式传输的实现方案中,一般采用HTTP/TCP来传输控制信息,而用RTP/UDP来传输实时多媒体数据. 1 实时传输 ...
- ESP32-mqtt笔记
基于ESP-IDF4.1 #include <stdio.h> #include <stdint.h> #include <stddef.h> #include & ...
- c语言:scanf(" %c",&bla); scanf("%c",&bla); 语句差别
%前有空格,%没有空格 scanf("%c",&c) 与 scanf(" %c",&c),后者只是在%前多了个空格,似乎没有什么区别,但使用起来 ...
- Command 'ifconfig' not found, but can be installed with: sudo apt install net-tools VM Ubuntu 解决方案
VMware下安装的Ubuntu 一开始由于Firefox连不上网,然后通过看了https://www.bbsmax.com/A/VGzlEGYJbq/这个文章之后,自己也测了一下,确实好用 但是if ...
- 从代码生成说起,带你深入理解 mybatis generator 源码
枯燥的任务 这一切都要从多年前说起. 那时候刚入职一家新公司,项目经理给我分配了一个比较简单的工作,为所有的数据库字段整理一张元数据表. 因为很多接手的项目文档都不全,所以需要统一整理一份基本的字典表 ...
- python + Poium 库操作
1.支持pip安装 pip install poium 2.基本用法 from poium import PageElement,Page,PageElements# 1.poium支持的8种定位方法 ...
- Dijkstra和堆优化
Dijkstra算法 由于我之前一直记的迪杰斯特拉的翻译导致我把dijkstra写成了dijstra--所以下文#define dijstra dijkstra 我以后叫她迪杰克斯歘! Dijskra ...
- java 8内置的四大核心函数式接口
Consumer<T> : 消费性接口 返回值 void accept(T t); public void happy(double money, Consumer<Double& ...
- 第三篇 -- HTML基础
买的课程学习 Web 前端标准 web前端技术指的不是某一项技术,而是一系列技术的集合,主要包括: html -- 结构标准:负责网页结构的搭建 css -- 样式标准/表现标准:负责网页的美化工作 ...