重新认识Tomcat(一)
Springboot内置tomcat如何处理前端请求
我用清晰、好懂、偏源码思路给你讲一遍:SpringBoot 内置 Tomcat 接收并处理前端请求的完整流程。你可以直接对应到源码里的关键类。
一、整体流程一句话总结
- Tomcat 启动监听端口(默认 8080)
- 浏览器发 HTTP 请求 → 被 Tomcat 接收
- Tomcat 解析请求,封装成
Request/Response - 交给 SpringMVC 的
DispatcherServlet分发 - 找到对应
@Controller/@RestController方法执行 - 返回结果,Tomcat 组装 HTTP 响应返回浏览器
二、详细链路(从网络到业务代码)
1. 内置 Tomcat 启动过程(SpringBoot 启动时)
- SpringBoot 自动配置
TomcatServletWebServerFactory - 创建并启动 Tomcat 实例(
Tomcat类) - 启动
Connector(监听 8080,默认 NIO 模型) - 注册
DispatcherServlet到 Tomcat 的容器
关键:Tomcat 是真正的Web 服务器,SpringMVC 是跑在上面的 Servlet 应用。
2. 请求进来:Tomcat 网络层接收
- 浏览器 TCP 三次握手 → 建立连接
- Tomcat NIO 线程(Acceptor/Poller) 监听 socket
- 读取 HTTP 报文(请求行、头、体)
- 封装成 Tomcat 内部的:
Request(org.apache.coyote.Request)Response
3. Tomcat 容器层:Engine → Host → Context → Wrapper
Tomcat 层级:
Connector → Engine → Host → Context → Wrapper → Servlet
Context:对应一个 Web 应用(你的 SpringBoot 项目)Wrapper:对应一个 Servlet(这里就是DispatcherServlet)- Tomcat 调用:
servlet.service(request, response)
4. 进入 SpringMVC:DispatcherServlet 核心分发
DispatcherServlet#doService() → doDispatch() 是核心:
-
获取 HandlerMapping根据 URL 找到对应的
HandlerMethod(你写的@GetMapping("/xxx")方法) -
获取 HandlerAdapter用来真正调用 Controller 方法(
RequestMappingHandlerAdapter) -
执行拦截器
HandlerInterceptor#preHandle -
执行 Controller 方法反射调用你的接口方法,参数解析(
@RequestParam/@RequestBody) -
处理返回值视图解析 /
@ResponseBody转 JSON(HttpMessageConverter) -
执行拦截器后置处理
postHandle/afterCompletion
5. 回到 Tomcat 输出响应
- SpringMVC 把结果写入
response - Tomcat 组装 HTTP 响应头、响应体
- 通过 socket 写回浏览器
- 关闭 / 复用连接
三、极简源码调用链(方便你断点追)
Acceptor/Poller 接收连接
→ CoyoteAdapter.service()
→ Request/Response 封装
→ StandardWrapperValve.invoke()
→ DispatcherServlet.service() → doDispatch()
→ HandlerMapping 找Controller
→ HandlerAdapter 执行方法
→ 返回结果写入Response
→ Tomcat 刷新输出流返回前端
四、关键角色总结
- Tomcat Connector:负责网络 IO、HTTP 解析
- Tomcat Container:负责 Servlet 管理、生命周期
- DispatcherServlet:SpringMVC 中央调度器
- HandlerMapping:URL → 控制器方法
- HandlerAdapter:执行控制器方法
- HttpMessageConverter:请求 / 响应数据转换(JSON 等)
Springboot内置tomcat的线程模型是怎样的
一、一句话先懂核心
内置 Tomcat 默认用 NIO 模型(非阻塞 IO),线程分三类:
- Acceptor 线程:接收 TCP 连接
- Poller 线程:监听连接的读写事件
- Worker(业务)线程:真正执行 Servlet、Controller 逻辑
二、完整线程模型(默认 NIO)
1. 三大线程组
(1)Acceptor 线程
- 作用:只负责监听端口、accept 新 TCP 连接
- 数量:默认 1 个(
acceptorThreadCount=1) - 不处理请求、不读数据,只做 “接客”
(2)Poller 线程(Selector 轮询)
- 作用:
- 把新连接注册到
Selector - 轮询
OP_READ/OP_WRITE事件 - 有可读数据时,把任务丢给 Worker 线程池
- 把新连接注册到
- 数量:默认
CPU核心数 <= 2 ? 1 : 2 - 属于 IO 事件线程,非常轻量,不能阻塞
(3)Worker 线程池(业务线程)
- 就是你配置的:
server: tomcat: threads: max: 200 # 最大业务线程 min-spare: 10 # 核心线程 - 作用:真正执行请求:解析 HTTP、走 Filter、Servlet、Controller、返回响应
- 这是你接口业务逻辑执行的线程
- 阻塞、耗时、数据库操作都在这里发生
2. 一条请求完整线程流转(必背)
- 浏览器建连接 → Acceptor 接收
- Acceptor 把连接交给 Poller
- Poller 监听可读事件
- 数据到了 → Poller 把任务提交给 Worker 线程池
- Worker 线程 执行:
- 解析 HTTP
- 走 FilterChain
- 进入 DispatcherServlet
- 执行你的 Controller
- 写完响应 → Worker 线程释放回池
关键点:一个请求从头到尾,只占用一个 Worker 线程,直到响应结束。Tomcat NIO 只是IO 多路复用,不是异步 Servlet 模式。
三、三种 IO 模式对比(内置 Tomcat 支持)
1. NIO(默认,SpringBoot 推荐)
- IO:非阻塞、多路复用(Selector)
- 连接数高、线程数少
- 适合:绝大多数 Web 项目
2. NIO2(APR/native 不推荐默认)
- JDK NIO.2(AsynchronousChannelGroup)
- 真正异步 IO
- 用得少,SpringBoot 不默认
3. BIO(传统阻塞)
- 一连接一线程
- 并发高就炸,已废弃
四、关键配置 & 线程数关系
server:
tomcat:
# Acceptor 线程,默认1,基本不用改
acceptor-thread-count: 1
# Poller 线程,默认自动
poller-thread-count: 2
# 业务线程池(最关键)
threads:
max: 200 # 最大并发请求线程
min-spare: 10
# 等待队列(线程满了后排队的连接数)
accept-count: 100
maxThreads:同时处理请求的最大业务线程数accept-count:连接队列长度,线程池满后,新连接在队列等着- 超过队列 → 直接拒绝(Connection refused)
五、容易踩坑的误区(面试高频)
-
Tomcat NIO ≠ 异步执行
- 只是 IO 非阻塞,Worker 线程还是同步阻塞执行整个请求
- 想真正异步,要用:
Callable、DeferredResult、WebFlux
-
maxThreads 不是越大越好
- 线程多 = 切换多、内存大
- 一般 IO 密集型:200~500
- CPU 密集型:接近 CPU 核心数
-
Acceptor/Poller 很少需要改默认配置基本最优。
六、极简总结(面试直接说)
SpringBoot 内置 Tomcat 默认 NIO 线程模型:
- Acceptor:收连接
- Poller:监听 IO 事件
- Worker 线程池:执行业务(Controller)
- 一个请求占用一个 Worker 线程直到返回
- 高并发靠 IO 多路复用扛连接,靠线程池扛业务
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)