【Spring源码16】SpringBoot内嵌Tomcat万字源码拆解!容器启动+端口绑定+Web容器底层全解析
【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容器:
-
创建 Tomcat 核心服务器实例
-
初始化端口(默认8080,读取配置文件自定义端口)
-
初始化线程池、连接池、超时时间
-
创建 Tomcat 上下文容器 ServletContext
-
注册 SpringMVC 核心 DispatcherServlet
-
注册所有过滤器、监听器
步骤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依赖实现容器替换,底层依然是工厂模式适配:
-
排除web starter中的tomcat依赖
-
引入undertow启动器依赖
-
容器自动匹配UndertowWebServerFactory
-
项目启动自动使用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底层源码实战教程!
更多推荐

所有评论(0)