美文网首页
SpringBoot系列:3.web启动流程简述

SpringBoot系列:3.web启动流程简述

作者: dothetrick | 来源:发表于2020-11-15 18:57 被阅读0次

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

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

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

    Spring的核心就是ApplicationContext,启动流程实际就是调用其子接口ConfigurableApplicationContextrefresh()方法。

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

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

    image

    因此,对于web启动流程可以分析ServletWebServerApplicationContextrefresh(),一个简化的启动流程如下:

    image

    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中对绑定逻辑的实现,主要函数调用流程如下:

    image

    可以看到,注册的大部分逻辑是在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的变量名称
    
    

    以上内容属个人学习总结,如有不当之处,欢迎在评论中指正

    相关文章

      网友评论

          本文标题:SpringBoot系列:3.web启动流程简述

          本文链接:https://www.haomeiwen.com/subject/eaznbktx.html