别再死记硬背!用故事教你理解Tomcat的请求处理机制

37 阅读6分钟



前阵子,一个粉丝在评论区问我:“小米,我最近在准备 Java 社招面试,面试官老喜欢问 Tomcat 的底层问题。上次他问我 ‘Tomcat 的 Container 是怎么处理请求的?’,我一时语塞,差点当场原地超度……”

哈哈哈,我懂那种感觉。

面试官微笑着看你,你的脑子一片空白,只剩一句话在循环播放——“我是谁,我在哪,我在干什么?”

所以今天,小米就来带你轻轻松松地搞懂:

Tomcat 的 Container 是怎么一步步处理请求的。

放心,我不讲死板的概念,我给你讲个故事,让你看懂、记住、还能讲出来。

Tomcat 的“家族体系”:一个层层递进的组织架构

想象一下,Tomcat 就像一个大型的公司。这个公司有四个层级的“部门”,它们分别叫:

  • Engine(引擎总管)
  • Host(主机经理)
  • Context(项目主管)
  • Wrapper(Servlet 包装员)

这些家伙统称为 Container(容器家族) 。听起来抽象?没关系,我们先来形象地感受一下它们的关系。

故事这样开始:

一天,一个 HTTP 请求——我们叫他“小请求”——敲响了 Tomcat 公司的大门。

“你好,我是一条请求,请问谁能帮我找到 http://localhost:8080/demo/hello ?”

门卫 Connector 接过话,说:“好的,你找的这家公司叫 Tomcat,我负责接客,你的请求我收到了。来,我送你去我们公司的内部处理中心——Container 部门。”

于是,“小请求”被交到了 Container 家族的门口。

接下来,就是一场层层转交的冒险。

Container 家族的分工:谁负责哪一摊?

小请求一路往里走,先见到了最上层的主管——Engine 容器

1. Engine:大总管

Engine 是整个容器链的老大。它不干活,但负责分派任务。

他看着请求说:“你这个请求是访问哪个虚拟主机的?哦,是 localhost,那我派你去找我们的 Host 部门经理。”

于是,小请求被派去了 Host 容器

2. Host:虚拟主机经理

Host 容器就像一台服务器上的“项目宿主”。

比如你在 Tomcat 的 conf/server.xml 里配置多个 ,就是有多个虚拟主机。

Host 问:“你是访问 /demo 这个项目吗?那你得去找我们的 Context 主管。”

3. Context:项目主管

Context 对应着一个 Web 应用,比如 /demo。

它就像一个项目经理,负责整个 Web 应用的生命周期、Servlet 注册、过滤器、监听器,统统管着。

Context 一看:“原来你是找 /hello 这个接口,那这个接口归我们 HelloServlet 处理,我让 Wrapper 去找它。”

Wrapper:Servlet 包装员

Wrapper 是最基层的容器,它直接包裹着一个个 Servlet。比如 HelloServlet、LoginServlet 等。

Wrapper 负责:

  1. 加载 Servlet 实例(第一次请求时)
  2. 调用 Servlet 的 service() 方法 来处理请求。

到这一步,小请求终于见到了它真正的“服务员”——HelloServlet。

Servlet 处理完请求后,返回一个 Response,小请求带着响应结果,顺着原路返回,回到 Connector,最后返回给浏览器。

整个流程,就像一场严密的公司运作。

层层传递的秘密:Pipeline 与 Valve

看到这里,你可能觉得这只是“分发层级”,但 Tomcat 可没那么简单。真正让它灵活强大的,是 Pipeline(管道)Valve(阀门) 机制。

想象一下:

每个容器不仅能“接力”,还能“拦截、加工、记录”。这就像每个部门门口都装了一套“流水线”系统。

请求经过时,可能会:

  • Valve 拦截做日志(类似 Filter);
  • 被修改 Header;
  • 被检测权限;
  • 最后才交给下一级。

而这套机制,就是 Tomcat 的拦截器体系

每个容器(Engine、Host、Context、Wrapper)都有自己的 Pipeline,每个 Pipeline 里可以装多个 Valve

请求从上往下传递时,会经过:

Engine → Host → Context → Wrapper

每一层都可以插自己的 Valve。

最后,到达 Wrapper 的 StandardWrapperValve 时,就会真正调用 Servlet.service() 方法。

这时候,小请求终于被执行完毕,响应数据被包装成 Response,再经过同样的 Valve 反向流出,一层层返回出去。

是不是有点像 SpringMVC 的 HandlerInterceptor + Filter 的合体版?

没错,这正是 Tomcat 的高灵活性所在。

用一口气总结整个流程

好,我们用一口气,把整个请求流程串起来。

  • Connector 接收请求: 解析 HTTP 请求,封装成 Request 和 Response 对象。
  • 传给 Engine 容器: Engine 根据虚拟主机名,找到对应的 Host。
  • Host 容器分发: Host 根据 URI 路径,找到对应的 Context(即某个 Web 应用)。
  • Context 查找 Servlet: Context 再根据 /hello 映射,找到对应的 Wrapper。
  • Wrapper 调用 Servlet: Wrapper 调用 Servlet 的 service() 方法执行业务逻辑。
  • 返回 Response: Response 沿着 Pipeline 反向返回,Connector 把结果写回浏览器。

整个过程用一句话总结就是:

Connector 收请求,Container 传下去,Servlet 干活,Valve 拦截,Response 回来。

这,就是 Tomcat 的核心“协作链”。

面试官会怎么问?

讲完原理,我们再来看看——面试官喜欢“挖坑”的地方。

问1:Container 有几种类型?各自作用?

答:

  • Engine:整个 Catalina 容器的顶层入口;
  • Host:代表一个虚拟主机;
  • Context:代表一个 Web 应用;
  • Wrapper:包装一个具体 Servlet。

问2:Tomcat 怎么找到目标 Servlet?

答:

  1. Connector 收请求;
  2. Engine 按域名匹配 Host;
  3. Host 按路径匹配 Context;
  4. Context 按映射匹配 Servlet(Wrapper)。

问3:Pipeline 和 Valve 是干嘛的?

答:

Pipeline 是管道模型,Valve 是具体的阀门实现,每个 Container 都有自己的 Pipeline,请求经过每一层 Pipeline 的 Valve,最终到达 Servlet。

问4:Wrapper 的 StandardWrapperValve 有什么作用?

答:

它是 Tomcat 调用 Servlet 的最终入口,会先初始化 Servlet 实例,再执行 service()。

面试时,如果你能讲出这些,还能带一点故事式的比喻,面试官基本就会露出那种“懂啊,这孩子懂行”的笑容。

用一个比喻,让你彻底记住

我最喜欢的比喻是:Tomcat 就像一个大型餐厅。

  • Connector:迎宾员,接待客人(请求)
  • Engine:总经理,决定送去哪个厨房(Host)
  • Host:厨房主管,一个厨房可以做多个菜系(多个项目)
  • Context:厨师长,负责一个具体菜系(Web 应用)
  • Wrapper:厨师本人(Servlet)
  • Valve:检查员、调味员,在菜品上桌前负责加料、质检、记录日志

当一道菜(请求)被送进来,从迎宾、分配、下单、烹饪到上菜,每个环节都协同工作。最终,顾客(浏览器)吃到的,就是 Servlet 输出的结果。

是不是一下就通了?

写在最后:理解架构,才能玩得更深

很多人学 Tomcat 只是停留在“启动一下服务器”、“看下日志”层面,但当你真正理解了它的容器架构,你会发现:

Tomcat 不只是“跑个 Servlet”那么简单。它是一套高度模块化的“请求处理流水线”,每一层都可以扩展、定制、拦截。

比如:

  • 想加监控?写个 Valve。
  • 想加权限?写个 Context 拦截器。
  • 想做负载?修改 Host 层逻辑。

理解了 Container,你就真正掌握了 Tomcat 的灵魂。

END

总结一句话送给你:

“懂 Connector,你会启动服务器;懂 Container,你能掌控服务器。”

下次再遇到面试官问“Tomcat 的 Container 是怎么处理请求的?”,你只要淡定地一笑,然后讲出“小请求进公司”的故事,他大概率会在心里默默打个 ——

“这个人,不光会背,还真懂。”

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!