zoukankan      html  css  js  c++  java
  • springboot mvc自动配置(一)自动配置DispatcherServlet和DispatcherServletRegistry

    所有文章

    https://www.cnblogs.com/lay2017/p/11775787.html

    正文

    springboot的自动配置基于SPI机制,实现自动配置的核心要点就是添加一个自动配置的类,SpringBoot MVC的自动配置自然也是相同原理。

    本文开始,我们将讨论Springboot下Servlet的web实现。所以,先找到对应的自动配置类。

    org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration

    DispatcherServletAutoConfiguration自动配置类

    我们打开该类

    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnClass(DispatcherServlet.class)
    @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
    public class DispatcherServletAutoConfiguration {
        //...
    }

    1、首先注意到,@Configuration表名这是一个配置类,将会被spring给解析。

    2、@ConditionalOnWebApplication意味着当时一个web项目,且是Servlet项目的时候才会被解析。

    3、@ConditionalOnClass指明DispatcherServlet这个核心类必须存在才解析该类。

    4、@AutoConfigureAfter指明在ServletWebServerFactoryAutoConfiguration这个类之后再解析,设定了一个顺序。

    总的来说,这些注解表明了该自动配置类的会解析的前置条件需要满足。

    其次,DispatcherServletAutoConfiguration类主要包含了两个内部类,分别是

    1、DispatcherServletConfiguration

    2、DispatcherServletRegistrationConfiguration

    顾名思义,前者是配置DispatcherServlet,后者是配置DispatcherServlet的注册类。什么是注册类?我们知道Servlet实例是要被添加(注册)到如tomcat这样的ServletContext里的,这样才能够提供请求服务。所以,DispatcherServletRegistrationConfiguration将生成一个Bean,负责将DispatcherServlet给注册到ServletContext中。

    配置DispatcherServletConfiguration

    我们先看看DispatcherServletConfiguration这个配置类

    @Configuration(proxyBeanMethods = false)
    @Conditional(DefaultDispatcherServletCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties({ HttpProperties.class, WebMvcProperties.class })
    protected static class DispatcherServletConfiguration {
    
        //...
    }

    @Conditional指明了一个前置条件判断,由DefaultDispatcherServletCondition实现。主要是判断了是否已经存在DispatcherServlet,如果没有才会触发解析。

    @ConditionalOnClass指明了当ServletRegistration这个类存在的时候才会触发解析,生成的DispatcherServlet才能注册到ServletContext中。

    最后,@EnableConfigrationProperties将会从application.properties这样的配置文件中读取spring.http和spring.mvc前缀的属性生成配置对象HttpProperties和WebMvcProperties。

    再看DispatcherServletConfiguration这个内部类的内部代码

    @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet(HttpProperties httpProperties, WebMvcProperties webMvcProperties) {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
        dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
        dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
        dispatcherServlet.setEnableLoggingRequestDetails(httpProperties.isLogRequestDetails());
        return dispatcherServlet;
    }
    
    @Bean
    @ConditionalOnBean(MultipartResolver.class)
    @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
    public MultipartResolver multipartResolver(MultipartResolver resolver) {
        // Detect if the user has created a MultipartResolver but named it incorrectly
        return resolver;
    }

    这个两个方法我们比较熟悉了,就是生成了Bean。

    dispatcherServlet方法将生成一个DispatcherServlet的Bean对象。比较简单,就是获取一个实例,然后添加一些属性设置。

    multipartResolver方法主要是把你配置的MultipartResolver的Bean给重命名一下,防止你不是用multipartResolver这个名字作为Bean的名字。

    配置DispatcherServletRegistrationConfiguration

    再看注册类的Bean配置

    @Configuration(proxyBeanMethods = false)
    @Conditional(DispatcherServletRegistrationCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties(WebMvcProperties.class)
    @Import(DispatcherServletConfiguration.class)
    protected static class DispatcherServletRegistrationConfiguration {
        //...
    }

    同样的,@Conditional有一个前置判断,DispatcherServletRegistrationCondition主要判断了该注册类的Bean是否存在。

    @ConditionOnClass也判断了ServletRegistration是否存在

    @EnableConfigurationProperties生成了WebMvcProperties的属性对象

    @Import导入了DispatcherServletConfiguration,也就是我们上面的配置对象。

    再看DispatcherServletRegistrationConfiguration的内部实现

    @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
    @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
            WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
        DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
                webMvcProperties.getServlet().getPath());
        registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
        registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
        multipartConfig.ifAvailable(registration::setMultipartConfig);
        return registration;
    }

    内部只有一个方法,生成了DispatcherServletRegistrationBean。核心逻辑就是实例化了一个Bean,设置了一些参数,如dispatcherServlet、loadOnStartup等。

    总结

    springboot mvc的自动配置类是DispatcherServletAutoConfigration,主要做了两件事:

    1)配置DispatcherServlet

    2)配置DispatcherServlet的注册Bean

  • 相关阅读:
    jqueryeasyui中创建复杂布局
    内表查询用到外表
    某人对为什么不搞.net,不搞web的原因
    眼睛痛的一些原因
    控件包含代码块(即 <% ... %>),因此无法修改控件集合(用户自定义控件中)
    明天留着看
    SqlServer 数据归档
    从 char 数据类型到 datetime 数据类型的转换导致 datetime 值越界。
    生成sql 脚本没有索引
    sqlserver 时间间隔
  • 原文地址:https://www.cnblogs.com/lay2017/p/11803794.html
Copyright © 2011-2022 走看看