• SpringBoot是如何集成了Tomcat呢?


        我们肯定对SpringBoot默认内部集成了Tomcat web环境不陌生,虽然reactive容器逐渐崭露头角,但相信大部分的用户还是使用了Tomcat的容器的。不知道是否有同学和我一样,对SpringBoot如何集成了tomcat有好奇,这里我们从springboot的源码中查看一下,它是如何集成tomcat的;

        先来看springboot的标准启动的代码:

    SpringApplication.run(SpringBootApplication.class, args);

    1. 首先,同名run方法中:

    1. public static ConfigurableApplicationContext run(Class[] primarySources, String[] args) {
    2. return new SpringApplication(primarySources).run(args);
    3. }

    可以找到创建了SpringApplication对象的代码,从构造方法我们可以找到一个关键点:

    this.webApplicationType = WebApplicationType.deduceFromClasspath();

    deduceFromClasspath方法会从环境里是否有特定的类来判断WebApplicationType,由于我们没有配置reactive,因此此处会返回WebApplicationType.SERVLET

    2. 分析完构造方法之后,我们来看一下run方法的内部,其中有一行:

    context = createApplicationContext();

    这个方法就会根据上一步的WebApplicationType来决定上下文;在这里我们会执行到

    contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);

    3. webServer的创建入口

    webServer的创建是在run方法的refreshContext中的。

    经过几个跳转我们来到了十分熟悉的,十分出名的 AbstractApplicationContext # refresh方法,重点关注它的onRefresh

    1. @Override
    2. protected void onRefresh() {
    3. super.onRefresh();
    4. try {
    5. createWebServer();
    6. }
    7. catch (Throwable ex) {
    8. throw new ApplicationContextException("Unable to start web server", ex);
    9. }
    10. }

    其中有一个createWebServer方法

    1. private void createWebServer() {
    2. WebServer webServer = this.webServer;
    3. ServletContext servletContext = getServletContext();
    4. if (webServer == null && servletContext == null) {
    5. ServletWebServerFactory factory = getWebServerFactory();
    6. this.webServer = factory.getWebServer(getSelfInitializer());
    7. }
    8. else if (servletContext != null) {
    9. try {
    10. getSelfInitializer().onStartup(servletContext);
    11. }
    12. catch (ServletException ex) {
    13. throw new ApplicationContextException("Cannot initialize servlet context", ex);
    14. }
    15. }
    16. initPropertySources();
    17. }

    这个方法先会创建一个webServer工厂类,默认情况下,就是TomcatServletWebServerFactory了!

    我们看下它的getWebServer方法:

    1. @Override
    2. public WebServer getWebServer(ServletContextInitializer... initializers) {
    3. Tomcat tomcat = new Tomcat();
    4. File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
    5. tomcat.setBaseDir(baseDir.getAbsolutePath());
    6. Connector connector = new Connector(this.protocol);
    7. tomcat.getService().addConnector(connector);
    8. customizeConnector(connector);
    9. tomcat.setConnector(connector);
    10. tomcat.getHost().setAutoDeploy(false);
    11. configureEngine(tomcat.getEngine());
    12. for (Connector additionalConnector : this.additionalTomcatConnectors) {
    13. tomcat.getService().addConnector(additionalConnector);
    14. }
    15. prepareContext(tomcat.getHost(), initializers);
    16. return getTomcatWebServer(tomcat);
    17. }

    哈哈,成功找到了。

    createWebServer接下来会设置webServer属性,最后调用initPropertySources方法(如果环境中存在servletContextInitParams/servletConfigInitParams属性,会对其进行一个替换),并不是关注的重点,我们先跳过;

    4. 我们跟踪到AbstractApplicationContext # refresh -> finishRefresh方法:

    1. @Override
    2. protected void finishRefresh() {
    3. super.finishRefresh();
    4. WebServer webServer = startWebServer();
    5. if (webServer != null) {
    6. publishEvent(new ServletWebServerInitializedEvent(webServer, this));
    7. }
    8. }

    这里会启动WebServer

    1. private WebServer startWebServer() {
    2. WebServer webServer = this.webServer;
    3. if (webServer != null) {
    4. webServer.start();
    5. }
    6. return webServer;
    7. }

    在默认情况下,我们就会调用到TomcatWebServer方法了;

  • 相关阅读:
    数据结构之<二叉搜索树>
    51单片机学习笔记_2 LED 模块
    Python进阶教学——装饰器与闭包
    实体属性映射框架mapstruct
    实战技巧位运算
    H5 <blockquote> 标签
    pytorch学习------TensorBoard的使用
    Java攻略集合之基础语法
    深入浅出学习透析Nginx服务器的基本原理和配置指南「进阶实践篇」
    MS5611的ZYNQ驱动试验之一 分析
  • 原文地址:https://blog.csdn.net/lhf2112/article/details/125882680