关于spring:SpringBoot系列3web启动流程简述

40次阅读

共计 2971 个字符,预计需要花费 8 分钟才能阅读完成。

本文简要介绍下 SpringBoot 中,web 我的项目启动时一些重要的流程:

  • SpringBoot 中用于 web 的 IOC 容器启动流程
  • HTTP 的 url 是如何和 controller 中的办法绑定的?
  • 罕用的 web 我的项目配置参数

SpringBoot 中用于 web 的 IOC 容器启动流程

Spring 的外围就是 ApplicationContext,启动流程理论就是调用其子接口ConfigurableApplicationContextrefresh()办法。

在 Spring 中,有一个 ConfigurableApplicationContext 的实现类 AbstractApplicationContext,该类中实现了 refresh() 的流程。SpringBoot 默认提供的启动类都是它的子类。

默认状况下,web 服务应用的就是 AnnotationConfigServletWebServerApplicationContext,它的父类是ServletWebServerApplicationContext,也是AbstractApplicationContext 的间接子类。类之间的继承关系如下:

因而,对于 web 启动流程能够剖析 ServletWebServerApplicationContextrefresh(),一个简化的启动流程如下:

AbstractApplicationContext中实现的 refresh()流程中,蕴含了两个办法 onRefresh()finishRefresh()

ServletWebServerApplicationContext就是通过重写这两个办法,实现了对 web server 的配置和启动。

来看下 ServletWebServerApplicationContextonRefresh()finishRefresh()

  • onRefresh()中次要是依据配置信息,初始化 web Server,默认应用的就是Tomcat,依赖tomcat-embed-core
  • 设置之后,会持续 IOC 的启动流程,解决我的项目中的 Bean
  • refresh() 的最初,会调用finishRefresh(),并启动Tomcat,这之后才能够失常解决 http 申请。
@Override
protected void onRefresh() {super.onRefresh();
  try {createWebServer();
  }
  catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);
  }
}
@Override
protected void finishRefresh() {super.finishRefresh();
  WebServer webServer = startWebServer();
  if (webServer != null) {publishEvent(new ServletWebServerInitializedEvent(webServer, this));
  }
}

HTTP 的 url 是如何和 controller 中的办法绑定的?

当提供 restful api 时,通常会在 Controller 类上应用 @RestController 注解,绑定的办法就是在该注解的解决逻辑中。

简略说下 spring 中注解的实现原理

在 Spring IOC 注入流程中会在解决 bean 的不同阶段,顺次调用一些接口的全副实现类,例如 InitializingBean,BeanPostProcessor 等。

SpringBoot 中的注解就是通过实现这些接口,在逻辑中判断 bean 是否持有指定注解,来对 bean 做非凡解决。

@RestController 等 web 注解的解决类次要是 RequestMappingHandlerMapping,该类间接实现了InitializingBean 接口,通过重写 afterPropertiesSet 办法实现解决逻辑。

url 和办法绑定的具体流程

上面次要看下 RequestMappingHandlerMapping 和其父类 AbstractHandlerMethodMapping 中对绑定逻辑的实现,次要函数调用流程如下:

能够看到,注册的大部分逻辑是在 AbstractHandlerMethodMapping 中,最终会把 url 和解决办法保留在一个 Hashmap 中。

上面对办法做简要阐明:

  • RequestMappingHandlerMapping.afterPropertiesSet()

    • 初始化配置,一些 url 解析器和解析规定。
  • AbstractHandlerMethodMapping.initHandlerMethods()processCandidateBean()

    • 从 IOC 的 beans 中,筛选出蕴含 @RestController 等注解的 controller bean。
  • AbstractHandlerMethodMapping.detectHandlerMethods(Object handler)

    • 检测 controller bean,筛选出蕴含 @PostMapping()@GetMapping()等注解的办法。
  • AbstractHandlerMethodMapping.MappingRegistry.register(T mapping, Object handler, Method method)

    • 初始化并将 url 和解决办法注册到 MappingRegistry.registry 成员中,理论是个 Hashmap

通过这个过程实现了 url 和办法的映射,后续接到 http 申请后,就会依据映射把申请路由到对应的办法上。

罕用的 web 我的项目配置参数

spring:
  redis:
    database: 0
    host: localhost
    port: 6379
  session:
    store-type: redis #session 的存储形式,集群部署时抉择 redis 在集群中共享 session
    timeout: 600s #session 的过期工夫
  main:
    web-application-type: servlet #web 我的项目的类型,影响应用的 ApplicationContext 的实现类,非 web 我的项目可设置为:none

server:
  tomcat:
    max-connections: 1024 #最大连接数
    accesslog:
      enabled: true #开启 accesslog,默认是 false,要设置为 true 才会记录 accesslog
      directory: /var/user-logs/service-logs #保留 accesslog 的门路
      pattern: "%t [%I] %a %r %s (%D ms)" #记录每行 log 的格局
      file-date-format: .yyyy-MM-dd-HH #log 文件的划分,默认是每天一个文件,可加上 HH 设置为按小时分 log 文件
  port: 8999 #服务启动端口
  servlet:
    context-path: /my-app #url 对立前缀
    session:
      cookie:
        name: myjsessionid #保留在 cookies 中的 session 的变量名称

以上内容属集体学习总结,如有不当之处,欢送在评论中斧正

正文完
 0