← blog 技术原理与实践 · 2026-08-30

Tomcat到底是什么?——一个“翻译官”的自我修养

解读 Tomcat 在网页应用中的位置与作用,以及为什么 Spring Boot 打包的 Jar 可以直接启动 Web 服务。

8 min read

很多初学者在学 Java Web 时,都会产生一个困惑:我写的 Java 代码明明只是普通的类和方法,它是怎么接收到浏览器发来的请求的?Tomcat 在其中到底扮演了什么角色?

今天这篇文章,就用最直白的语言,把这件事彻底讲清楚。


一、先搞清楚一个前提:Jar 包不能”接电话”

很多人第一次部署项目时,会以为”把代码打成 Jar 包,运行起来,前端就能访问了”。

但真相是:

  • Jar 包本质上只是一个压缩包(类似 zip),里面装着编译好的 .class 文件、配置文件和资源文件。
  • 它没有任何网络监听能力。你直接运行一个纯业务逻辑的 Jar,它执行完 main 方法就退出了,根本不知道什么是 HTTP 请求。

打个比方:Jar 包就像一本写好了菜谱的书,但它自己不会做饭,也听不见客人点菜的声音。

那谁来”听”客人的需求,把菜做出来,再端给客人呢?

答案是:Tomcat。


二、Tomcat 的核心角色:协议翻译官

前端(浏览器)只懂 HTTP 协议,Java 业务代码只懂 Java 对象。两者语言不通,无法直接对话。

Tomcat 就是站在它们中间的翻译官 + 接线员。

请求进来时(翻译方向:HTTP → Java)

步骤发生了什么
1浏览器发起 HTTP 请求(包含 URL、方法、参数、Header 等)
2Tomcat 的 Connector 组件监听端口(默认 8080),接收到原始 TCP 数据流
3Tomcat 解析这段原始文本,提取出路径、参数、请求头等信息
4将解析结果封装成标准的 HttpServletRequest 对象
5根据 URL 路径,找到对应的 Servlet(你写的业务代码),调用其方法

响应出去时(翻译方向:Java → HTTP)

步骤发生了什么
1你的 Java 代码处理完业务逻辑,得到一个结果对象(如 List<Order>)
2结果被序列化为 JSON / HTML 等格式
3写入 HttpServletResponse 对象,设置状态码(200)、Content-Type 等
4Tomcat 将 Response 对象拼接成标准的 HTTP 响应文本流
5通过网络发回浏览器,前端渲染页面

一句话总结:Tomcat 负责把 HTTP 请求”翻译”成 Java 能处理的对象传进业务层,再把业务层的返回值”翻译”成 HTTP 响应送回前端。


三、完整闭环:一个请求的一生

把上面的内容串起来,一个完整的 Web 请求生命周期是这样的:

用户点击按钮
    ↓
浏览器构建 HTTP 请求,发送到服务器 8080 端口
    ↓
Tomcat Connector 监听并接收
    ↓
解析为 HttpServletRequest 对象
    ↓
根据 URL 路由,找到对应的 Servlet
    ↓
调用你的 Java 业务代码(查数据库、调接口、做计算...)
    ↓
业务代码将结果写入 HttpServletResponse
    ↓
Tomcat 将 Response 序列化为 HTTP 响应报文
    ↓
浏览器接收响应,渲染页面
    ↓
用户看到结果

整个过程中,你的 Java 代码只关心业务逻辑(查订单、算价格、校验权限),完全不需要自己去解析 TCP 字节流、拼 HTTP 报文。这些”脏活累活”全部由 Tomcat 代劳。


四、那 Spring Boot 的 java -jar 是怎么回事?

你可能会问:

“不对啊,我用 Spring Boot 打包成 Jar,直接 java -jar app.jar 就能启动 Web 服务了,不是说 Jar 不能接请求吗?”

这里有一个”障眼法”:

Spring Boot 把 Tomcat 也打包进了你的 Jar 里。

当你运行 java -jar springboot-app.jar 时,实际发生的事情是:

  1. Jar 里的 main 方法启动;
  2. 内部自动创建并启动了一个嵌入式 Tomcat 实例;
  3. 将你的 Controller / Servlet 注册到这个 Tomcat 中;
  4. Tomcat 开始监听端口,等待请求。

所以表面上是”Jar 在接收请求”,本质上依然是 Tomcat 在做网络通信和协议翻译,只不过它被藏在了 Jar 包内部,你感知不到而已。

这也是为什么 Spring Boot 被称为”约定优于配置”——它帮你省去了手动安装、配置、部署 Tomcat 的繁琐步骤,但底层机制从未改变。


五、一个比喻,彻底记住

角色比喻职责
前端(浏览器)说外语的客人发出需求(HTTP 请求)
Tomcat翻译官 + 服务员听懂客人的话,转达给后厨;把后厨的菜端给客人
Java 业务代码后厨厨师只做菜(处理业务逻辑),不跟客人直接交流
Jar 包菜谱书记载了怎么做菜,但自己不会动
数据库食材仓库提供原材料

没有翻译官,客人和厨师永远无法沟通。这就是 Tomcat 存在的意义。


六、总结

前端只懂 HTTP 协议,Java 业务代码只懂 Java 对象。Tomcat 是两者之间的”协议翻译官”和”网络连接器”。 它负责监听端口、解析请求、路由分发、封装响应。而 Jar 包本身只是代码的载体,不具备网络通信能力。

理解了这一点,你就真正搞懂了 Java Web 最底层的运行逻辑。后续无论是学习 Spring MVC 的 DispatcherServlet 路由、还是理解 Nginx 反向代理到 Tomcat 的链路,都会水到渠成。


如果这篇文章帮你理清了思路,欢迎点赞收藏。下一篇我们聊聊:Spring MVC 的 DispatcherServlet 是如何在 Tomcat 之上做”二次路由”的。

七、DispatcherServlet 的”二次路由”——Tomcat 翻译完之后,Spring 内部再分一次

你已经理解了 Tomcat 是”翻译官”,那 DispatcherServlet 就是 Tomcat 翻译完之后,Spring MVC 内部的”二次调度员”。

先明确一个关键事实:Tomcat 根本不认识你的 Controller

你的 UserController、OrderController 这些类,虽然加了 @Controller 注解,但它们只是普通的 Java 类,没有实现 HttpServlet 接口,Tomcat 完全不知道它们的存在。

整个项目中,Tomcat 真正认识的、注册在案的 Servlet 只有一个——DispatcherServlet。

Spring 在启动时,把 DispatcherServlet 注册到了 Tomcat 的根路径 / 上,意思是:所有请求,不管什么 URL,统统先交给 DispatcherServlet 处理。

两层路由的分工

这就形成了两层路由机制:

层级负责者做什么
第一层路由Tomcat根据 URL 匹配到具体的 Servlet → 发现是 / → 交给 DispatcherServlet
第二层路由DispatcherServlet在 Spring 内部再根据 URL 匹配到具体的 Controller 方法

打个比方:Tomcat 是大楼前台,所有来访者先到前台。前台只认识一个部门——“调度部”(DispatcherServlet)。来访者到了调度部之后,调度部再根据来访者的具体需求,把他带到对应的工位(Controller 方法)。

DispatcherServlet 内部做了什么?

当 Tomcat 把请求交给 DispatcherServlet 后,它调用的是 doDispatch() 方法,这是整个 Spring MVC 的心脏。

核心流程就五步:

请求进入 doDispatch()
    ↓
① HandlerMapping:根据 URL 找到对应的 Controller 方法(Handler)
    ↓
② HandlerAdapter:找到能"执行"这个方法的适配器
    ↓
③ 执行拦截器链(Interceptor)的 preHandle
    ↓
④ 通过适配器,反射调用你的 Controller 方法
    ↓
⑤ 处理返回值(JSON 序列化 / 视图渲染),写回 Response

关键组件解析

HandlerMapping —— “查号台”

Spring 启动时,会扫描所有带 @Controller 或 @RestController 的类,把每个 @RequestMapping 标注的路径和对应的 Java 方法建立映射关系,存成一张”路由表”。

请求进来时,HandlerMapping 就拿着请求的 URL 去这张表里查:

“路径是 /users/123,谁负责处理?” → “是 UserController.getUser() 方法”

HandlerAdapter —— “执行器”

DispatcherServlet 不直接调用你的方法,而是通过 HandlerAdapter 来执行。这是适配器模式的经典应用——DispatcherServlet 不关心你的处理器到底长什么样(可能是注解方式、可能是接口方式),它只面向 HandlerAdapter 接口编程,由适配器去适配不同的处理器类型。

完整链路一图流

浏览器请求 GET /users/123
    ↓
【第一层:Tomcat】
Tomcat 接收 HTTP 请求,解析为 HttpServletRequest
    ↓
Tomcat 路由:URL 匹配到 DispatcherServlet(映射路径 /)
    ↓
调用 DispatcherServlet.service()
    ↓
【第二层:Spring MVC】
DispatcherServlet.doDispatch() 开始二次路由
    ↓
HandlerMapping 查表:/users/123 → UserController.getUser()
    ↓
HandlerAdapter 执行 UserController.getUser(123)
    ↓
方法返回 User 对象
    ↓
HttpMessageConverter 将 User 序列化为 JSON
    ↓
写入 HttpServletResponse,返回给 Tomcat
    ↓
Tomcat 将 Response 发回浏览器
    ↓
用户看到 JSON 数据

一句话总结

Tomcat 做的是”粗路由”:把请求从网络层带到 Java 世界,交给 DispatcherServlet。 DispatcherServlet 做的是”细路由”:在 Spring 内部根据 URL 精确匹配到具体的 Controller 方法,再通过适配器执行。

两者分工明确,各司其职。Tomcat 管”网络协议 → Servlet”,DispatcherServlet 管”Servlet → 业务方法”。


理解了这两层路由,你回头看 Spring Boot 的自动配置、拦截器、异常处理等机制,就都会豁然开朗。

Sources

No external sources for this entry.

Related