【Spring源码16】SpringBoot内嵌Tomcat万字源码拆解!容器启动+端口绑定+Web容器底层全解析

🔥 Spring全家桶源码连载系列(SpringBoot进阶核心)

上一篇15篇,我们彻底吃透了SpringBoot自动配置、SPI机制、条件注解 核心原理。

今天我们解决 SpringBoot 最经典、面试必问的底层问题:

为什么SpringBoot项目不用部署外置Tomcat?

内嵌Tomcat是何时创建、何时启动的?

端口号8080是如何绑定的?修改端口底层原理是什么?

内嵌Tomcat和外置Tomcat到底有什么本质区别?

SpringBoot是如何实现Web容器的自动创建与启停?

很多人写了几年 SpringBoot,一直以为 Tomcat 是“自带的黑盒”,完全不懂底层启动源码。

本篇手撕内嵌Tomcat全套启动源码,打通 SpringBoot Web 容器最后一块底层壁垒,彻底搞定所有容器相关面试题!

一、前置认知:什么是内嵌Tomcat?

1.1 传统SSM vs SpringBoot容器模式

传统SSM项目

项目打成 War 包,部署到外置Tomcat容器,由外部Tomcat负责加载项目、解析Web工程、监听端口、处理请求。

SpringBoot项目

内置 Tomcat 核心依赖,无需外置容器,项目启动时自动创建、初始化、启动内嵌Tomcat,main方法启动即服务启动,直接监听端口对外提供服务。

1.2 核心优势

  • 无需单独安装、配置、部署Tomcat

  • Jar包一键启动,部署极其简单,适配云原生、容器化部署

  • 容器版本与框架版本绑定,彻底解决版本冲突问题

  • 容器生命周期由Spring统一管控,启动、关闭、销毁更优雅

1.3 核心结论(面试必背)

SpringBoot内嵌Tomcat本质:将Tomcat服务器以Jar依赖的方式嵌入项目,由SpringBoot程序主动启动,而非外部容器加载项目。

二、内嵌Tomcat核心依赖与自动配置入口

2.1 依赖溯源

只要引入web启动器,自动带入内嵌Tomcat依赖:

spring-boot-starter-web

底层自动依赖:spring-boot-starter-tomcat

这也是为什么新建SpringBoot Web项目,默认自带Tomcat环境。

2.2 自动配置核心类

内嵌Tomcat所有功能,全部由 SpringBoot 自动配置类实现:

ServletWebServerFactoryAutoConfiguration(Web容器工厂自动配置)

TomcatServletWebServerFactory(Tomcat容器工厂核心类)

结合上一篇学的自动配置原理:

引入web依赖 → 触发条件注解生效 → 自动创建Tomcat容器工厂Bean → 项目启动时创建并启动内嵌Tomcat。

三、核心组件:Web容器工厂机制(底层核心)

3.1 为什么需要工厂?

SpringBoot 不止支持 Tomcat,还支持 Jetty、Undertow 等多款Web容器。

为了统一容器创建规范,SpringBoot 抽象出 WebServerFactory 容器工厂接口,通过工厂模式适配不同容器。

3.2 三大主流Web容器

  • Tomcat:SpringBoot默认容器,均衡稳定、生态最全

  • Jetty:轻量级、高性能、适合长连接场景

  • Undertow:高并发、低内存、性能极强

3.3 Tomcat容器工厂核心作用

TomcatServletWebServerFactory 核心职责:

  • 创建 Tomcat 服务器实例

  • 初始化端口、编码、连接数、线程池等配置

  • 创建上下文容器、注册Servlet、过滤器

  • 启动Tomcat、绑定端口、监听请求

四、内嵌Tomcat完整启动源码全链路(逐行拆解)

结合 SpringBoot 启动流程,完整拆解 从容器初始化到端口监听 全流程,面试可直接口述满分。

步骤1:SpringBoot启动,创建IoC容器并刷新

执行 SpringApplication.run(),创建注解版IoC容器,执行 refresh() 刷新流程。

在容器刷新过程中,加载Web容器自动配置类,注册Tomcat工厂Bean。

步骤2:触发容器刷新后置动作(onRefresh)

SpringBoot 重写了容器刷新的后置方法onRefresh(),这是Web容器启动的真正入口。

核心源码:ServletWebServerApplicationContext#onRefresh()

该方法会调用 createWebServer() 创建Web容器。

步骤3:获取Tomcat容器工厂Bean

从IoC容器中获取自动配置好的 TomcatServletWebServerFactory工厂Bean。

如果没有自定义容器工厂,默认使用内置Tomcat工厂。

步骤4:工厂创建Tomcat WebServer

调用工厂的 getWebServer() 方法,开始构建Tomcat容器:

  1. 创建 Tomcat 核心服务器实例

  2. 初始化端口(默认8080,读取配置文件自定义端口)

  3. 初始化线程池、连接池、超时时间

  4. 创建 Tomcat 上下文容器 ServletContext

  5. 注册 SpringMVC 核心 DispatcherServlet

  6. 注册所有过滤器、监听器

步骤5:启动内嵌Tomcat容器

Tomcat 实例初始化完成后,调用 start() 方法启动容器。

底层开启Socket服务,绑定端口、监听IP请求,正式对外提供HTTP服务。

步骤6:容器启动完成,项目就绪

Tomcat启动成功后,SpringBoot打印启动成功日志,项目正式运行,接收前端HTTP请求。

至此,内嵌Tomcat完整启动流程结束!

五、核心细节深度拆解(面试高频)

5.1 端口号配置底层原理

默认端口:8080,可通过 server.port 自定义修改。

底层加载逻辑:

  • 容器启动时读取 application 配置文件的 server.port 属性

  • Tomcat工厂初始化时将配置端口绑定到Tomcat服务器

  • 启动Socket服务时监听指定端口

端口冲突原理:端口被占用时,Socket绑定失败,直接抛出端口占用异常,项目启动失败。

5.2 DispatcherServlet何时注册?

SpringMVC核心前端控制器,并非手动配置,而是:

WebMvcAutoConfiguration自动创建DispatcherServlet Bean,并在Tomcat初始化阶段,自动注册到Tomcat容器中。

这也是SpringBoot无需配置Servlet、直接使用Web功能的底层原因。

5.3 内嵌Tomcat生命周期与Spring容器绑定

  • Spring容器启动 → 触发Tomcat启动

  • Spring容器关闭 → 触发Tomcat优雅关闭

  • 容器异常销毁 → Tomcat同步销毁释放端口

完全由Spring统一管控,生命周期一致,资源释放更安全。

六、内嵌Tomcat vs 外置Tomcat(面试必问)

全网最清晰对比,直接背诵满分答案:

对比维度

内嵌Tomcat(SpringBoot)

外置Tomcat(SSM)

启动方式

程序main方法主动启动容器

外置Tomcat启动,加载War包项目

打包方式

Jar包,内置所有依赖

War包,依赖外置容器运行

容器归属

Spring容器内部组件,统一管控

独立外部服务,不归Spring管理

部署方式

一键java -jar启动,简单高效

上传替换War包,重启Tomcat,繁琐

版本控制

项目内置版本,无冲突

依赖外置Tomcat版本,易出现版本不兼容

适用场景

微服务、云原生、容器化部署

传统单体老旧项目

七、拓展:如何替换默认Tomcat为Undertow?

SpringBoot默认Tomcat,可通过排除Tomcat依赖、引入Undertow依赖实现容器替换,底层依然是工厂模式适配:

  1. 排除web starter中的tomcat依赖

  2. 引入undertow启动器依赖

  3. 容器自动匹配UndertowWebServerFactory

  4. 项目启动自动使用Undertow容器,无需修改业务代码

完美体现 SpringBoot 工厂模式 + 条件注解 + 开闭原则 的顶级设计!

八、高频面试真题满分必背

1、SpringBoot为什么不需要外置Tomcat?

SpringBoot内置Tomcat依赖,通过自动配置机制初始化Tomcat容器工厂,在Spring容器刷新阶段自动创建并启动内嵌Tomcat,绑定端口监听请求。项目自身包含完整Web运行环境,无需依赖外置Tomcat容器,直接Jar包启动即可对外提供Web服务。

2、内嵌Tomcat的启动时机?

在Spring IoC容器刷新的后置阶段onRefresh()中触发,通过Web容器工厂创建Tomcat实例,完成初始化、端口绑定、容器启动,晚于Bean创建、早于项目启动完成。

3、SpringBoot如何实现多Web容器适配?

基于工厂模式设计,抽象WebServerFactory统一容器创建规范,通过条件注解根据项目依赖自动匹配Tomcat、Jetty、Undertow对应的容器工厂,实现无需改代码、动态适配不同Web容器。

4、内嵌Tomcat和外置Tomcat的最大区别?

核心区别是容器归属与启动方式:内嵌Tomcat是项目内置组件,由Spring容器统一生命周期管理,Jar包独立启动;外置Tomcat是独立外部服务,项目以War包形式被外部容器加载运行,版本与生命周期不受项目管控。

5、端口修改底层原理?

SpringBoot启动时加载配置文件server.port属性,Tomcat容器工厂初始化时读取该配置,绑定到Tomcat的Socket监听端口,覆盖默认8080端口,实现自定义端口配置。

九、本篇总结 & 下期预告

本篇总结

本篇彻底吃透 SpringBoot Web容器核心底层,补齐SpringBoot最后一块核心短板:

  • 理解内嵌Tomcat的核心设计思想与优势

  • 掌握容器工厂模式、自动配置底层逻辑

  • 熟记Tomcat完整启动源码链路与时机

  • 搞懂端口绑定、Servlet注册、容器生命周期原理

  • 精通内嵌与外置Tomcat的核心区别与面试考点

至此,SpringBoot 启动流程 + 自动配置 + 内嵌容器 三大核心底层全部吃透!

下期预告

下一篇第十七篇(SpringBoot完结篇),更新 SpringBoot核心注解 + 高频坑点 + 失效场景全集!汇总SpringBoot所有面试坑点、经典失效问题、核心注解底层,收官整个Spring全家桶源码系列!

💡 往期推荐 & 系列连载

本Spring全家桶源码系列从零入门、层层拆解,全网最系统的Spring底层源码实战教程!

更多推荐