spring boot源码_springboot源码架构解析DispatcherServletAutoConfiguration

说在前面

前期回顾

sharding-jdbc源码解析 更新完毕

spring源码解析 更新完毕

spring-mvc源码解析 更新完毕

spring-tx源码解析 更新完毕

spring-boot源码解析 更新完毕

rocketmq源码解析 更新完毕

dubbbo源码解析 更新完毕

netty源码解析 更新完毕

spring源码架构更新完毕

spring-mvc源码架构更新完毕

springboot源码架构更新中

github https://github.com/tianheframe

sharding-jdbc源码解析 更新完毕

rocketmq源码解析 更新完毕

seata 源码解析 更新完毕

dubbo 源码解析 更新完毕

netty 源码解析 更新完毕

源码解析

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration Spring DispatcherServlet的自动配置。应该适用于已经存在嵌入式servlet容器的独立应用程序,也适用于使用SpringBootServletInitializer的可部署应用程序。

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)@Configuration@ConditionalOnWebApplication@ConditionalOnClass(DispatcherServlet.class)@AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)public class DispatcherServletAutoConfiguration {

监测到DispatcherServlet calss类,在配置EmbeddedServletContainerAutoConfiguration之后配置该类

  public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";

默认转发servlet是dispatcherServlet

  @Configuration  @Conditional(DefaultDispatcherServletCondition.class)  @ConditionalOnClass(ServletRegistration.class)  @EnableConfigurationProperties(WebMvcProperties.class)  protected static class DispatcherServletConfiguration {

执行DefaultDispatcherServletCondition条件判断,加载到ServletRegistration class类,加载WebMvcProperties配置文件

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition#getMatchOutcome

@Override    public ConditionOutcome getMatchOutcome(ConditionContext context,        AnnotatedTypeMetadata metadata) {      ConditionMessage.Builder message = ConditionMessage          .forCondition("Default DispatcherServlet");//      获取BeanFactory      ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//      根据类型从beanFactory找出DispatcherServlet实现类的beanNames      List dispatchServletBeans = Arrays.asList(beanFactory          .getBeanNamesForType(DispatcherServlet.class, false, false));      if (dispatchServletBeans.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {        return ConditionOutcome.noMatch(message.found("dispatcher servlet bean")            .items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));      }      if (beanFactory.containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {        return ConditionOutcome            .noMatch(message.found("non dispatcher servlet bean")                .items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));      }      if (dispatchServletBeans.isEmpty()) {        return ConditionOutcome            .match(message.didNotFind("dispatcher servlet beans").atAll());      }      return ConditionOutcome.match(message          .found("dispatcher servlet bean", "dispatcher servlet beans")          .items(Style.QUOTE, dispatchServletBeans)          .append("and none is named " + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));    }

从BeanFactory中监测org.springframework.web.servlet.DispatcherServlet类型的bean,组装监测信息。

@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)    public DispatcherServlet dispatcherServlet() {      DispatcherServlet dispatcherServlet = new DispatcherServlet();      dispatcherServlet.setDispatchOptionsRequest(          this.webMvcProperties.isDispatchOptionsRequest());      dispatcherServlet.setDispatchTraceRequest(          this.webMvcProperties.isDispatchTraceRequest());      dispatcherServlet.setThrowExceptionIfNoHandlerFound(          this.webMvcProperties.isThrowExceptionIfNoHandlerFound());      return dispatcherServlet;    }

初始化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;    }

监测MultipartResolver类型的bean,没检测到multipartResolver名称的bean,创建MultipartResolver

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration

@Configuration  @Conditional(DispatcherServletRegistrationCondition.class)  @ConditionalOnClass(ServletRegistration.class)  @EnableConfigurationProperties(WebMvcProperties.class)  @Import(DispatcherServletConfiguration.class)  protected static class DispatcherServletRegistrationConfiguration {

执行DispatcherServletRegistrationCondition类监测逻辑,监测到ServletRegistration这个bean,加载WebMvcProperties配置,引入DispatcherServletConfiguration的BeanDefinition

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition

  @Override    public ConditionOutcome getMatchOutcome(ConditionContext context,        AnnotatedTypeMetadata metadata) {//      获取BeanFactory      ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();//      检查dispatcherServlet并组装匹配结果      ConditionOutcome outcome = checkDefaultDispatcherName(beanFactory);      if (!outcome.isMatch()) {        return outcome;      }//      检查dispatcherServletRegistration      return checkServletRegistration(beanFactory);    }

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition#checkDefaultDispatcherName

private ConditionOutcome checkDefaultDispatcherName(        ConfigurableListableBeanFactory beanFactory) {//      获取beanFactory中DispatcherServlet类型的beanNames      List servlets = Arrays.asList(beanFactory          .getBeanNamesForType(DispatcherServlet.class, false, false));//      beanFactory中是否包含dispatcherServlet这个bean      boolean containsDispatcherBean = beanFactory          .containsBean(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);//      BeanFactory中包含dispatcherServlet这个bean,不包含dispatcherServlet这个beanName      if (containsDispatcherBean          && !servlets.contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) {//        组装匹配结果        return ConditionOutcome            .noMatch(startMessage().found("non dispatcher servlet")                .items(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME));      }      return ConditionOutcome.match();    }

org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition#checkServletRegistration

private ConditionOutcome checkServletRegistration(        ConfigurableListableBeanFactory beanFactory) {      ConditionMessage.Builder message = startMessage();//      从beanFactory中查找ServletRegistrationBean的实现类的beanNames      List registrations = Arrays.asList(beanFactory          .getBeanNamesForType(ServletRegistrationBean.class, false, false));//      BeanFactory中是够包含dispatcherServletRegistration bean      boolean containsDispatcherRegistrationBean = beanFactory          .containsBean(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);//      组装匹配结果      if (registrations.isEmpty()) {        if (containsDispatcherRegistrationBean) {          return ConditionOutcome              .noMatch(message.found("non servlet registration bean").items(                  DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));        }        return ConditionOutcome            .match(message.didNotFind("servlet registration bean").atAll());      }      if (registrations          .contains(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)) {        return ConditionOutcome.noMatch(message.found("servlet registration bean")            .items(DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));      }      if (containsDispatcherRegistrationBean) {        return ConditionOutcome            .noMatch(message.found("non servlet registration bean").items(                DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));      }      return ConditionOutcome.match(message.found("servlet registration beans")          .items(Style.QUOTE, registrations).append("and none is named "              + DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME));    }
private final ServerProperties serverProperties;

serverProperties

org.springframework.boot.autoconfigure.web.ServerProperties

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)public class ServerProperties    implements EmbeddedServletContainerCustomizer, EnvironmentAware, Ordered {

文件属性名以server开始

private Integer port;

服务端口

private String contextPath;

servlet上下文路径

private String servletPath = "/";

servlet路径

private final Map<String, String> contextParameters = new HashMap<String, String>();

servletContext参数

private Integer connectionTimeout;

连接器在关闭连接之前等待另一个HTTP请求的时间(以毫秒为单位)。未设置时,将使用连接器容器特定的缺省值。使用-1值表示没有超时(即无限超时)。

private final Tomcat tomcat = new Tomcat();

tomcat

org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat

private File basedir;

tomcat基础目录

private int backgroundProcessorDelay = 10;  

调用backgroundProcess方法之间的延迟(以秒为单位)。

private int maxThreads = 200;

最大线程数

private int minSpareThreads = 10;

最小工作线程数

private int maxHttpPostSize = 2097152;

HTTP post内容的最大字节数。

private int maxConnections = 10000;

服务器将在任何给定时间接受和处理的最大连接数。一旦达到限制,操作系统仍然可以基于“acceptCount”属性接受连接。

private int acceptCount = 100;

使用所有可能的请求处理线程时传入连接请求的最大队列长度。

private final Jetty jetty = new Jetty();

jetty

org.springframework.boot.autoconfigure.web.ServerProperties.Jetty

private int maxHttpPostSize = 200000;

HTTP post或put内容的最大字节数。

private Integer acceptors = -1;

要使用的接受器线程数。当值为-1(默认值)时,接受器的数量来自操作环境。

private Integer selectors = -1;

要使用的选择器线程数。当值为-1(默认值)时,选择器的数量来自操作环境。

private Session session = new Session();

session

org.springframework.boot.autoconfigure.web.ServerProperties.Session

private Integer timeout;

session超时时间

private File storeDir;

存储路径

@Override  public void customize(ConfigurableEmbeddedServletContainer container) {    if (getPort() != null) {      container.setPort(getPort());    }    if (getAddress() != null) {      container.setAddress(getAddress());    }    if (getContextPath() != null) {      container.setContextPath(getContextPath());    }    if (getDisplayName() != null) {      container.setDisplayName(getDisplayName());    }    if (getSession().getTimeout() != null) {      container.setSessionTimeout(getSession().getTimeout());    }    container.setPersistSession(getSession().isPersistent());    container.setSessionStoreDir(getSession().getStoreDir());    if (getSsl() != null) {      container.setSsl(getSsl());    }    if (getJspServlet() != null) {      container.setJspServlet(getJspServlet());    }    if (getCompression() != null) {      container.setCompression(getCompression());    }    container.setServerHeader(getServerHeader());    if (container instanceof TomcatEmbeddedServletContainerFactory) {      getTomcat().customizeTomcat(this,          (TomcatEmbeddedServletContainerFactory) container);    }    if (container instanceof JettyEmbeddedServletContainerFactory) {      getJetty().customizeJetty(this,          (JettyEmbeddedServletContainerFactory) container);    }    if (container instanceof UndertowEmbeddedServletContainerFactory) {      getUndertow().customizeUndertow(this,          (UndertowEmbeddedServletContainerFactory) container);    }    container.addInitializers(new SessionConfiguringInitializer(this.session));    container.addInitializers(new InitParameterConfiguringServletContextInitializer(        getContextParameters()));  }

定制化ConfigurableEmbeddedServletContainer

public String getServletMapping() {    if (this.servletPath.equals("") || this.servletPath.equals("/")) {      return "/";    }    if (this.servletPath.contains("*")) {      return this.servletPath;    }    if (this.servletPath.endsWith("/")) {      return this.servletPath + "*";    }    return this.servletPath + "/*";  }

设置servletPath

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)    @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)    public ServletRegistrationBean dispatcherServletRegistration(        DispatcherServlet dispatcherServlet) {//      mapping默认是/*      ServletRegistrationBean registration = new ServletRegistrationBean(          dispatcherServlet, this.serverProperties.getServletMapping());      registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);      registration.setLoadOnStartup(          this.webMvcProperties.getServlet().getLoadOnStartup());      if (this.multipartConfig != null) {        registration.setMultipartConfig(this.multipartConfig);      }      return registration;    }

如果检测到DispatcherServlet bean就初始化dispatcherServletRegistration

说在最后

本次解析仅代表个人观点,仅供参考。

6eae956d2e59461d523a5f6f305b16b9.gif

扫码进入技术微信群

78ea436716238e02e97b83ab109cf778.png 39d05f41bd891f39f27714b032cf5f67.png 0ba59a8d27294b44cc3b85865c2f8e43.png钉钉技术群

7f1801a5b6e098484d8f52fa81c8b7b6.png

qq技术群

c5f01a7c9cca6bf54d319f07f8d7c650.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值