官方文档目录:

https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-spring-mvc

 1. Spring MVC auto-configuration

  Spring Boot 自动配置好了SpringMVC,以下是SpringBoot对SpringMVC的默认配置:

WebMvcAutoConfiguration)

  - Inclusion of `ContentNegotiatingViewResolver` and `BeanNameViewResolver` beans.
  - 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))

    • public class WebMvcAutoConfiguration {
      @Bean
      @ConditionalOnMissingBean
      public InternalResourceViewResolver defaultViewResolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setPrefix(this.mvcProperties.getView().getPrefix());
      resolver.setSuffix(this.mvcProperties.getView().getSuffix());
      return resolver;
      } @Bean
      @ConditionalOnBean({View.class})
      @ConditionalOnMissingBean
      public BeanNameViewResolver beanNameViewResolver() {
      BeanNameViewResolver resolver = new BeanNameViewResolver();
      resolver.setOrder(2147483637);
      return resolver;
      } @Bean
      @ConditionalOnBean({ViewResolver.class})
      @ConditionalOnMissingBean(
      name = {"viewResolver"},
      value = {ContentNegotiatingViewResolver.class}
      )
      public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
      ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
      resolver.setContentNegotiationManager(
        (ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
      resolver.setOrder(-2147483648);
      return resolver;
      }
      ......
      }

    - ContentNegotiatingViewResolver:只配置一个@RequestMapping, 匹配多个 url

  • public class ContentNegotiatingViewResolver implements ViewResolver, Ordered, InitializingBean { 
        @Nullable
    privateList<ViewResolver> viewResolvers; //视图解析器 //初始化方法
    protected void initServletContext(ServletContext servletContext) {
    //从容器中根据ViewResolver类型获取所有的视图解析器Collection<ViewResolver> matchingBeans = BeanFactoryUtils
    .beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
    ViewResolver viewResolver;
    if (this.viewResolvers == null) {
    this.viewResolvers = new ArrayList(matchingBeans.size());
    Iterator var3 = matchingBeans.iterator(); //遍历所有的视图解析器
    while(var3.hasNext()) {
    viewResolver = (ViewResolver)var3.next();
    if (this != viewResolver) {
    //将所有的视图解析器加入到本地变量
    this.viewResolvers.add(viewResolver);
    }
    }
    } else {
    for(int i = 0; i < this.viewResolvers.size(); ++i) {
    viewResolver = (ViewResolver)this.viewResolvers.get(i);
    if (!matchingBeans.contains(viewResolver)) {
    String name = viewResolver.getClass().getName() + i;
    this.obtainApplicationContext().getAutowireCapableBeanFactory().initializeBean(viewResolver, name);
    }
    }
    } AnnotationAwareOrderComparator.sort(this.viewResolvers);
    this.cnmFactoryBean.setServletContext(servletContext);
    } @Nullable
    publicView 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) {//只配置一个@RequestMapping, 匹配多个 url,所以要获取多个
    List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);//获取所有候选的视图对象
    View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);//获取最佳视图对象(根据参数或类型选取)
    if (bestView != null) {
    return bestView;
    }
    } }
  • 自定义ViewResolver加入到Spring容器
  • //springBoot启动类注解,包含@Configuration
    @SpringBootApplication
    public class DemoApplication {
    public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
    }
    //将自定义的ViewResolver加入到Spring容器中
    @Bean
    public ViewResolver myViewResolver() {
    return new MyViewResover();
    }
    //自定义ViewResover
    public static class MyViewResover implements ViewResolver {
    @Nullable
    @Override
    public View resolveViewName(String s, Locale locale) throws Exception {
    return null;
    }
    }
    }
  • 当SpringBoot项目启动,随便发一个请求,进到DispatcherServlet的DoDispatch()方法时,能够获取到所有的ViewResolver,包括自定义的,被包含在了ContentNegotiatingViewResolver里

    

  - 总结:如何定制视图解析器ViewResolver?

    根据@WebMvcAutoConfiguration

        ——》 @Bean ContentNegotiatingViewResolver viewResolver()

            ——》initServletContext()中根据类型加载容器中所有的ViewResolver

    我们可以自己给容器中添加一个视图解析器,@Bean加入到容器中,SpringBoot便自动的将其组合进来;

  关于视图解析器详情在SprintMVC知识点中学习

 这些前面章节已有学过

  - Support for serving static resources, including support for WebJars (see below).静态资源文件夹路径,webjars

  - Static `index.html` support. 静态首页访问

  - Custom `Favicon` support (see below). favicon.ico


- 自动注册了 of `Converter`, `GenericConverter`, `Formatter` beans.

  - Converter:转换器; public String hello(User user):类型转换使用Converter      (如果页面传参和User对象类型一一对应,不用转换,如果对应不上就需要转换)
  - `Formatter` 格式化器; 2017.12.17   /   2017-12-17  / 2017/12/17===Date;  (1:字符串转日期;2:按照给定的格式转)

    •     
@Configuration
@ConditionalOnWebApplication(
type = ConditionalOnWebApplication.Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration { @Configuration
@Import({org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {
private final ListableBeanFactory beanFactory; @Bean
public FormattingConversionService mvcConversionService() {
WebConversionService conversionService = new WebConversionService(this.mvcProperties.getDateFormat());
this.addFormatters(conversionService);
return conversionService;
} protected void addFormatters(FormatterRegistry registry) {
this.configurers.addFormatters(registry);
} //添加格式化器
public void addFormatters(FormatterRegistry registry) {
//容器中符合Converter类型的bean都被格式化注册器FormatterRegistry注册进来
Iterator var2 = this.getBeansOfType(Converter.class).iterator(); while(var2.hasNext()) {
Converter<?, ?> converter = (Converter)var2.next();
registry.addConverter(converter);
} //容器中符合GenericConverter类型的bean都被格式化注册器FormatterRegistry注册进来
var2 = this.getBeansOfType(GenericConverter.class).iterator(); while(var2.hasNext()) {
GenericConverter converter = (GenericConverter)var2.next();
registry.addConverter(converter);
} //容器中符合Formatter类型的bean都被格式化注册器FormatterRegistry注册进来
var2 = this.getBeansOfType(Formatter.class).iterator(); while(var2.hasNext()) {
Formatter<?> formatter = (Formatter)var2.next();
registry.addFormatter(formatter);
} /**
* 从容器中获取所有从属于此类型的Bean
* 自己添加的格式化器转换器,我们只需要放在容器中即可
*/
private <T> Collection<T> getBeansOfType(Class<T> type) {
return this.beanFactory.getBeansOfType(type).values();
}
}
}
}

 

  - HttpMessageConverter:SpringMVC用来转换Http请求和响应的;返回结果将  User    ——》转化为  Json;

  - `HttpMessageConverters` 是从容器中确定;获取所有的HttpMessageConverter;

  •           
  • //@Configuration包含了@Component
    @Configuration
    public class WebMvcAutoConfiguration {
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {
    private final ObjectProvider<HttpMessageConverters> messageConvertersProvider; //通过构造方法从容器中注入进来
    public WebMvcAutoConfigurationAdapter(ObjectProvider<HttpMessageConverters> messageConvertersProvider,其它参数) {
    this.messageConvertersProvider = messageConvertersProvider;
    ......
    }
    }
    } //@Configuration包含了@Component
    @Configuration
    public class HttpMessageConverters implements Iterable<HttpMessageConverter<?>> {
    private final List<HttpMessageConverter<?>> converters; //
    public HttpMessageConverters(HttpMessageConverter... additionalConverters) {
    this((Collection) Arrays.asList(additionalConverters));
    }
    //通过构造方法从容器中注入进来
    public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) {
    this(true, additionalConverters);
    }
    }

     自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)

  - Automatic registration of `MessageCodesResolver` (see below).定义错误代码生成规则

  - Automatic use of a `ConfigurableWebBindingInitializer` bean (see below).

    我们可以配置一个ConfigurableWebBindingInitializer来替换默认的;(添加到容器)

      ```初始化WebDataBinder;
      ```请求数据=====JavaBean;

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 RequestMappingHandlerMappingRequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.


 总结:如何修改SpringBoot的默认配置?

​   1)、SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,

    如果没有,才自动配置;

    如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;

9 Web开发——springmvc自动配置原理的更多相关文章

  1. spring boot @EnableWebMvc禁用springMvc自动配置原理。

    说明: 在spring boot中如果定义了自己的java配置文件,并且在文件上使用了@EnableWebMvc 注解,那么sprig boot 的默认配置就会失效.如默认的静态文件配置路径:&quo ...

  2. springboot08(springmvc自动配置原理)

    MVC WebMvcAutoConfiguration.java @ConditionalOnMissingBean(name = "viewResolver", value = ...

  3. SpringBoot学习(七)-->SpringBoot在web开发中的配置

    SpringBoot在web开发中的配置 Web开发的自动配置类:在Maven Dependencies-->spring-boot-1.5.2.RELEASE.jar-->org.spr ...

  4. Springboot 系列(三)Spring Boot 自动配置原理

    注意:本 Spring Boot 系列文章基于 Spring Boot 版本 v2.1.1.RELEASE 进行学习分析,版本不同可能会有细微差别. 前言 关于配置文件可以配置的内容,在 Spring ...

  5. SpringBoot:配置文件及自动配置原理

    西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! SpringBoot ...

  6. springboot核心技术(二)-----自动配置原理、日志

    自动配置原理 配置文件能配置的属性参照 1.自动配置原理: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration 2).@Enable ...

  7. Spring Boot自动配置原理

    使用Spring Boot之后,一个整合了SpringMVC的WEB工程开发,变的无比简单,那些繁杂的配置都消失不见了,这 是如何做到的? 一切魔力的开始,都是从我们的main函数来的,所以我们再次来 ...

  8. SpringBoot入门一:基础知识(环境搭建、注解说明、创建对象方法、注入方式、集成jsp/Thymeleaf、logback日志、全局热部署、文件上传/下载、拦截器、自动配置原理等)

    SpringBoot设计目的是用来简化Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,SpringBoot致力于在蓬勃发 ...

  9. SpringBoot自动配置原理

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...

随机推荐

  1. Android提供的layout文件存放位置

    在编程的过程中,会用到android.R.layout下的一些常量.与这些常量对应的,Android提供了对应点的layout布局文件. android.jar中有对应的xml文件,但是打开的时候通常 ...

  2. SVG to Image in js

    SVG to Image in js SVG to Image https://image.online-convert.com/convert-to-svg https://stackoverflo ...

  3. 用java编网页的学习流程,我的一些小心得(初学java到高深运用)

    (1)java基础:首先得会写int,String,for循环,数组,**等等(熟练各种基础的关键字,各种java自带的排序,随即等等算法)什么是封装,继承,多态,然后private,public,p ...

  4. 读取excel思路

    1.输入地址 2.输入指定的sheet  通过sheet()[]方式指定 3.输入执行的单元位置 通过 .cell_value(x,y)方式指定 示例 data = xlrd.open_workboo ...

  5. BZOJ2214[Poi2011]Shift——模拟

    题目描述 Byteasar bought his son Bytie a set of blocks numbered from to and arranged them in a row in a ...

  6. Thymeleaf+SpringMVC,如何从模板中获取数据(转)

    在一个典型的SpringMVC应用中,带@Controller注解的类负责准备数据模型Map的数据和选择一个视图进行渲染.这个模型Map对视图进行完全的抽象,在使用Thymeleaf的情况下,它将是一 ...

  7. MT【12】三点坐标求面积

    $L_1,L_2$是O发出的两条射线,C是一个常数,一条动直线$l$分别与$L_1,L_2$交于A,B两点.$S_{\Delta ABC}=C$,求A,B的中点D的轨迹方程.(2012北大自主招生) ...

  8. Android GPS定位测试(附效果图)

    今天因为工作需要,把以前编写的一个GPS测试程序拿出来重新修改了一下.这个程序说起来有些历史了,是我11年编写的,那时候学了Android开发没多久,算是一个实验性的作品.现在工作需要,重新拿出来修整 ...

  9. [luogu2149][bzoj1880][SDOI2009]Elaxia的路线【拓扑排序+最短路+DP】

    题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间 ...

  10. luogu4932 浏览器 (拆)

    分析1的个数的奇偶性: 奇xor奇=偶xor偶=偶 奇xor偶=奇 所以只要统计1的个数是奇数的数的个数 和 是偶数的个数 乘一起就行了 直接用bitset来做,虽然常数很小/数据随机可以过,但复杂度 ...