SpringBoot——MVC原理
更多内容,前往 IT-BLOG
一、SpringMVC自动配置
SpringMVC auto-configuration:SpringBoot 自动配置好了SpringMVC。以下是 SpringBoot 对 SpringMVC的默认配置:(WebMvcAutoConfiguration)
【1】包括 ContentNegotiatingViewResolver 和 BeanNameViewResolver 如下:
1 @Bean
2 @ConditionalOnBean({ViewResolver.class})
3 @ConditionalOnMissingBean(
4 name = {"viewResolver"},
5 value = {ContentNegotiatingViewResolver.class}
6 )
7 //存在于 WebMvcAutoConfiguration.java
8 public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
9 ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
10 resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
11 resolver.setOrder(-2147483648);
12 return resolver;
13 }
14
15 //进入ContentNegotiatingViewResolver对象,查找解析视图的方法resolveViewName()
16 public View resolveViewName(String viewName, Locale locale) throws Exception {
17 RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
18 Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
19 List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
20 if(requestedMediaTypes != null) {
21 //获取候选的视图对象
22 List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
23 //选择最适合的视图对象
24 View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
25 if(bestView != null) {
26 return bestView;
27 }
28 }
29
30 //进入上面的getCandidateViews()方法,查看获取的视图解析器,发现SpringBoot是将所有的视图解析器获取到viewResolvers,挨个遍历获取。
31 private List<View> getCandidateViews(String viewName, Locale locale, List<MediaType> requestedMediaTypes) throws Exception {
32 List<View> candidateViews = new ArrayList();
33 Iterator var5 = this.viewResolvers.iterator();
34
35 while(var5.hasNext()) {
【2】自动配置了 ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
【3】ContentNegotiatingViewResolver:组合所有的视图解析器的;
1 //进入ContentNegotiatingViewResolver发现初始化视图解析器的时候,是从容器中BeanFactoryUtils获取所有的视图解析器。
2 protected void initServletContext(ServletContext servletContext) {
3 Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
4 this.getApplicationContext(), ViewResolver.class).values();
5 if(this.viewResolvers == null) {
【4】如何定制:我们可以自己给容器中添加一个视图解析器;自动的将其组合进来;
1 @Bean
2 @ConditionalOnProperty(prefix = "spring.mvc", name = "date‐format")//在文件中配置日期格式化的规则
3 public Formatter<Date> dateFormatter() {
4 return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
5 }
6
7 //举个栗子如下:
8 //可以自定义一个视图解析器,放入容器,springboot就会自动识别,继承viewreserve
9 @Bean
10 public MyView myView(){
11 return new MyView();
12 }
13 //需要实现ViewResolver接口
14 private static class MyView implements ViewResolver{
15
16 @Override
17 public View resolveViewName(String s, Locale locale) throws Exception {
18 return null;
19 }
20 }
【5】服务对静态资源的支持,静态资源文件夹路径,webjars等。静态首页访问,自定义favicon.ico 图标文件的支持。
【6】自动注册了 of Converter , GenericConverter , Formatter beans;
○ Converter:转换器; public String hello(User user):类型转换使用Converter,String转 int等等。
○ Formatter 格式化器; 2017.12.17===Date,源码如下:可以看到格式可以通过 spring.mvc.date-format调整。
1 @Bean
2 @ConditionalOnProperty(
3 prefix = "spring.mvc",
4 name = {"date-format"}
5 )
6 public Formatter<Date> dateFormatter() {
7 return new DateFormatter(this.mvcProperties.getDateFormat());
8 }
○ 自己添加的格式化器转换器,我们只需要放在容器中即可,上面代码块有演示。
【7】支持 HttpMessageConverters:
○ HttpMessageConverter:SpringMVC用来转换 Http请求和响应的;User用 Json方式写出去;
○ HttpMessageConverters 是从容器中确定;获取所有的 HttpMessageConverter;
○ 自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)
【8】自动注册 MessageCodesResolver,定义错误代码生成规则。自动使用 ConfigurableWebBindingInitializer类;
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
return (ConfigurableWebBindingInitializer)this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
}
它是从容器中获取 ConfigurableWebBindingInitializer 的,从而可知,我们可以配置一个 ConfigurableWebBindingInitializer来替换默认的(添加到容器),如果没有配置会初始化一个Web数据绑定器:
//初始化Web数据绑定器,作用就是将请求数据绑定到JavaBean中,参数等,涉及数据转换等等
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
initializer.setConversionService(this.mvcConversionService());
initializer.setValidator(this.mvcValidator());
initializer.setMessageCodesResolver(this.getMessageCodesResolver());
return initializer;
}
【9】org.springframework.boot.autoconfigure.web:web的所有自动场景;上面能够得到的主要思想就是:如何修改Springboot的默认配置,1)、在自动配置很多组件的时候,先看容器中有木有用户自己配置的(@Bean,@Component)如果有就是用用户配置的,如果没有就是用自动配置的,因为底层使用了@ConditionalOnMiss注解来判断,容器中是否已经存在此类配置。2)、如果有些组件可以配置多个,比如视图解析器(ViewResolver)将用户配置的和自己默认的组合起来。
扩展 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.
【1】根据我们之前的配置 xml来进行扩展:
<mvc:view‐controller path="/hello" view‐name="success"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean></bean>
</mvc:interceptor>
</mvc:interceptors>
【2】SpringBoot 编写一个配置类(@Configuration),继承 WebMvcConfigurerAdapter类型,不能标注 @EnableWebMvc。 继承抽象类既保留了所有的自动配置,也能用我们扩展的配置;
1 //使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
2 @Configuration
3 public class MyMvcConfig extends WebMvcConfigurerAdapter {
4 @Override
5 public void addViewControllers(ViewControllerRegistry registry) {
6 // super.addViewControllers(registry);
7 //浏览器发送 /yintong 请求来到 success ,视图映射,当没有业务逻辑的时候就比较方便
8 registry.addViewController("/yintong").setViewName("success");
9 }
10 }
原理:
【1】WebMvcAutoConfiguration 是 SpringMVC的自动配置类;
【2】在做其他自动配置时会导入;@Import(EnableWebMvcConfiguration.class);
1 @Configuration
2 public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
3 private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
4 //从容器中获取所有的WebMvcConfigurer
5 @Autowired(required = false)
6 public void setConfigurers(List<WebMvcConfigurer> configurers) {
7 if (!CollectionUtils.isEmpty(configurers)) {
8 this.configurers.addWebMvcConfigurers(configurers);
9 //一个参考实现;将所有的WebMvcConfigurer相关配置都来一起调用;
10 @Override
11 public void addViewControllers(ViewControllerRegistry registry) {
12 for (WebMvcConfigurer delegate : this.delegates) {
13 delegate.addViewControllers(registry);
14 }
15 }
16 }
17 }
【3】容器中所有的 WebMvcConfigurer都会一起起作用;
【4】我们的配置类也会被调用;
【5】效果:SpringMVC 的自动配置和我们的扩展配置都会起作用;
二、全面接管SpringMVC
让所有 SpringMVC的自动配置都失效。使用我们需要的配置,需要在配置类中添加 @EnableWebMvc即可。非常不推荐,不然使用 SpringBoot开发干嘛,哈哈。
1 //使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
2 @EnableWebMvc
3 @Configuration
4 public class MyMvcConfig extends WebMvcConfigurerAdapter {
5 @Override
6 public void addViewControllers(ViewControllerRegistry registry) {
7 // super.addViewControllers(registry);
8 //浏览器发送 /atguigu 请求来到 success
9 registry.addViewController("/atguigu").setViewName("success");
10 }
11 }
原理:为什么 @EnableWebMvc自动配置就失效了?
【1】@EnableWebMvc 的核心组合注解:
1 @Import(DelegatingWebMvcConfiguration.class)
2 public @interface EnableWebMvc {
【2】我们打开上面导入的 DelegatingWebMvcConfiguration 类,会发现其继承了 WebMvcConfigurationSupport。
1 @Configuration
2 public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
【3】我们看下 SpringBoot自动配置的文件,发现如下:@ConditionalOnMissingBean(WebMvcConfigurationSupport.class),可知当容器中存在 WebMvcConfigurationSupport类时,就不会导入自动配置的类了,第二步导入的就是这个类。
1 @Configuration
2 @ConditionalOnWebApplication
3 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
4 WebMvcConfigurerAdapter.class })
5 //容器中没有这个组件的时候,这个自动配置类才生效
6 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
7 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
8 @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
9 ValidationAutoConfiguration.class })
10 public class WebMvcAutoConfiguration {
【4】@EnableWebMvc 将 WebMvcConfigurationSupport 组件导入进来;
【5】导入的 WebMvcConfigurationSupport 只是 SpringMVC最基本的功能;
结论:在 SpringBoot 中会有非常多的 xxxConfigurer 帮助我们进行扩展配置。同时,在 SpringBoot 中也会有很多的xxxCustomizer 帮助我们进行定制配置。
----关注公众号,获取更多内容----
SpringBoot——MVC原理的更多相关文章
- SpringBoot底层原理及分析
一,Spring Boot简介 1.什么是Spring Boot: SpringBoot是由Pivotal团队提供的框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程. 该框架使用了特 ...
- springboot mvc自动配置(一)自动配置DispatcherServlet和DispatcherServletRegistry
所有文章 https://www.cnblogs.com/lay2017/p/11775787.html 正文 springboot的自动配置基于SPI机制,实现自动配置的核心要点就是添加一个自动配置 ...
- 这一次搞懂SpringBoot核心原理(自动配置、事件驱动、Condition)
@ 目录 前言 正文 启动原理 事件驱动 自动配置原理 Condition注解原理 总结 前言 SpringBoot是Spring的包装,通过自动配置使得SpringBoot可以做到开箱即用,上手成本 ...
- 全网最深分析SpringBoot MVC自动配置失效的原因
前言 本来没有计划这一篇文章的,只是在看完SpringBoot核心原理后,突然想到之前开发中遇到的MVC自动失效的问题,虽然网上有很多文章以及官方文档都说明了原因,但还是想亲自看一看,本以为很简单的事 ...
- Springboot MVC 自动配置
Springboot MVC 自动配置 官方文档阅读 https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#w ...
- ASP.NET MVC原理
仅此一文让你明白ASP.NET MVC原理 ASP.NET MVC由以下两个核心组成部分构成: 一个名为UrlRoutingModule的自定义HttpModule,用来解析Controller与 ...
- spring MVC原理
spring MVC原理 Spring MVC工作流程图 图一 图二 Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt D ...
- Spring框架和MVC原理
Spring框架和MVC原理 目录 Spring框架 SpringMVC工作原理 参考资料 回到顶部 Spring框架 Spring当前框架有20个jar包,大致可以分为6大模块: Core Cont ...
- SpringBoot启动原理及相关流程
一.springboot启动原理及相关流程概览 springboot是基于spring的新型的轻量级框架,最厉害的地方当属自动配置.那我们就可以根据启动流程和相关原理来看看,如何实现传奇的自动配置 二 ...
- Spring MVC 原理探秘 - 容器的创建过程
1.简介 在上一篇文章中,我向大家介绍了 Spring MVC 是如何处理 HTTP 请求的.Spring MVC 可对外提供服务时,说明其已经处于了就绪状态.再次之前,Spring MVC 需要进行 ...
随机推荐
- SpringBoot项目启动
SpringBoot项目与其他项目启动方式有些不同. 查看是否是SpringBoot项目,可以查看在项目的pom.xml中是否有引入SpringBoot: 上图中就是对应的spring-boot.若有 ...
- flutter 使用阿里iconfont图标库
1. 打开Iconnfont,选择自己想要的图标添加到购物车! 2,在右上角点开购物车选择下载代码. 3. 解压下载的代码压缩包,我们可以看到一个iconfont.ttf 4. 在项目根目录下创建一个 ...
- 什么叫IOCSABS呢
所谓的IOCSABS,就是全新的管理技术,是结合客户端管理与网络平台管理为一体的创新观念及技术, IOCSABS? (what is IOCSABS?) 英文的全称为Integrated Of ...
- WEB攻击与防御技术 pikachu——关于暴力破解
首先打开XAMPP 然后在网上下载pikachu平台压缩包 解压缩即可.之后进入到XAMPP的文件夹 将pikachu文件夹放到htdoces内就完成了pikachu平台的搭建~ 之后在xampp中点 ...
- Python-pytest -> Selenium之异常处理
Selenium之异常处理: 引用的库:(可以查看库里提供的异常类) from selenium.common.exceptions import ElementNotVisibleException ...
- word在指定页面设置页码
需求:比如,毕业论文前面几页要求罗马数字(摘要-目录)(这里设置页码格式即可完成),后面全是阿拉伯数字(这里比较难搞,以下方法是解决这里的) 方法: 1. 光标移到指定页面的第一个字符所在的位置前 2 ...
- Erlang Mnesia数据库迁移方法
本文参考https://blog.csdn.net/yangzm/article/details/51686249 需求 因为一些原因,需要把一个Mnesia节点的数据库搬迁到另一个节点,然后弃用原来 ...
- mysql查询mapper返参类型为List
List<String> lists = mapper.select(); 返参类型为List,查询没有数据的时候,lists不会为null,lists.size() 为 0.
- 美国:KDB 986446 D01已生效
1.美国FCC认证新要求 继2022年11月25日FCC发布了FCC 22-84法规禁止授权被认为对美国国家安全构成威胁的通信和视频监控设备后,2023年1月24日FCC又发布了KDB 986446 ...
- ceph PG 故障状态
PG 故障状态 Creating(创建中)在创建POOL时,需要指定PG的数量,此时PG的状态便处于creating,意思是Ceph正在创建PG Peering(互联中)peering的作用主要是在P ...