重新认识Tomcat(三)
HTTP 服务器:管网络、HTTP 解析、静态文件,不懂 JavaServlet 容器:管运行 Java Web 应用、Servlet、Session,依赖 HTTP 服务器提供请求Tomcat 同时包含两者,所以既是 HTTP 服务器,又是 Servlet 容器Nginx (HTTP) + Tomcat (Servlet 容器)配合使用HTTP 服务器:所有语言都有,负责 TCP、HTTP、网络
http服务器和servelet容器有什么不同
HTTP 服务器 和 Servlet 容器 到底有啥区别?为什么 Tomcat 既是 HTTP 服务器又是 Servlet 容器?
你现在困惑的点,本质就是:它们管的层级不一样、职责完全分开。
一、先给你一句终极结论
- HTTP 服务器:只懂 HTTP 协议、网络、静态文件,不懂 Java、Servlet、Controller
- Servlet 容器:只懂 Servlet 规范、运行 Java Web 应用、管理 Servlet/Filter/Session,不懂底层网络 HTTP 解析
Tomcat = HTTP 服务器 + Servlet 容器它把两件事都干了,所以你会混淆。
二、HTTP 服务器是干嘛的?(举例:Nginx、Apache httpd、Tomcat 的 Connector 部分)
职责(只做底层)
- 监听端口(80、443、8080)
- 处理 TCP 连接
- 解析 HTTP 请求报文(头、方法、URL、body)
- 返回 HTTP 响应
- 能返回静态资源:html、css、js、jpg
- 不懂任何 Java 代码,完全不执行 Servlet
你可以理解:
HTTP 服务器 = 收发快递的驿站只负责拆包、打包、传输,不关心里面是什么业务。
三、Servlet 容器是干嘛的?(举例:Tomcat 的 Container 部分、Jetty、Undertow)
职责(只做 Java Web 上层)
- 实现 Servlet 规范
- 加载、管理、运行 Servlet
- 管理 Filter、Listener、Session
- 给 Servlet 提供
Request/Response对象 - 调度请求到对应的 Servlet
- 不关心底层网络怎么读 HTTP,只拿解析好的对象用
你可以理解:
Servlet 容器 = 业务办公室只管处理业务逻辑,不管快递怎么送过来。
四、一张表秒懂区别
| 维度 | HTTP 服务器 | Servlet 容器 |
|---|---|---|
| 核心功能 | 处理网络、HTTP 协议、静态文件 | 运行 Java Web 应用、管理 Servlet |
| 懂不懂 Java/Servlet | 完全不懂 | 必须懂 Servlet 规范 |
| 主要做什么 | 接收请求、解析 HTTP、返回响应 | 执行 Servlet、Filter、Session、业务代码 |
| 典型软件 | Nginx、Apache httpd | Tomcat、Jetty、Undertow |
| 对应 Tomcat 哪部分 | Connector(连接器) | Container(容器) |
五、用生活例子彻底讲透(你一下就通)
场景:用户点一个接口 /user/list
-
浏览器发 HTTP 请求
-
HTTP 服务器(Tomcat Connector)
- 接到网络数据
- 解析出:URL=/user/list,方法 GET
- 封装成
Request对象 - 自己不处理,交给 Servlet 容器
-
Servlet 容器(Tomcat Container)
- 拿到 Request
- 找到
DispatcherServlet - 交给 Spring MVC
- 执行你的
@Controller - 把结果写到 Response
-
HTTP 服务器
- 拿到 Response
- 组装成 HTTP 报文
- 发回浏览器
六、为什么要分开?(架构意义)
-
职责单一
- HTTP 服务器:专注高性能网络 IO、并发、静态资源
- Servlet 容器:专注业务运行、Java 规范
-
真实部署结构(你以后必会遇到)
浏览器 → Nginx(HTTP服务器) → Tomcat(Servlet容器)
- Nginx 做反向代理、负载均衡、静态资源、HTTPS
- Tomcat 只跑 Java 业务
这就是:HTTP 服务器 和 Servlet 容器分工配合。
七、回到你最关心的:SpringBoot 内置 Tomcat
- Tomcat 里的 Connector = HTTP 服务器
- Tomcat 里的 Container = Servlet 容器
- SpringBoot 应用 = 跑在 Servlet 容器里的 Web 应用
- 请求流程:
浏览器 ↓ Connector(HTTP服务器:解析HTTP) ↓ Container(Servlet容器:执行Servlet/Controller) ↓ 返回响应
八、极简总结(背这几句就行)
- HTTP 服务器:管网络、HTTP 解析、静态文件,不懂 Java
- Servlet 容器:管运行 Java Web 应用、Servlet、Session,依赖 HTTP 服务器提供请求
- Tomcat 同时包含两者,所以既是 HTTP 服务器,又是 Servlet 容器
- 真实线上:Nginx (HTTP) + Tomcat (Servlet 容器) 配合使用
那其他语言呢
不光 Java,所有语言的 Web 服务,架构思路完全一样,只是名字不同。
你刚才理解的这套:HTTP服务器 <-> 应用容器 <-> 业务代码是通用架构,不是 Java 独有。
先把通用模型抽出来(所有语言都遵守)
不管什么语言,Web 请求一定分两层:
-
HTTP 服务器(通用层)
- 处理 TCP、HTTP 协议、解析请求、发响应
- 负责网络、并发、长连接、静态文件
- 不执行业务代码
-
应用运行层(语言专属层)
- 执行业务逻辑
- 管理路由、控制器、中间件、连接池等
- 不懂底层 HTTP 解析
Java 只是把这两层打包在了 Tomcat 里,别的语言是分开或换名字。
我直接给你对标:其他语言对应什么?
1. Java 你已经懂了
- HTTP 服务器:Tomcat Connector / Nginx
- 应用容器(Servlet 容器):Tomcat Container
- 业务:Servlet / SpringMVC / Controller
2. Go 语言
- HTTP 服务器:Go 内置 net/http自己实现 HTTP 解析、TCP 监听
- 应用框架:Gin、Echo、Beego负责路由、中间件、参数解析
- 结构:
浏览器 → Go内置HTTP服务器 → Gin路由 → Handler函数
Go 把 HTTP 服务器直接嵌到语言里了,不需要外置 Tomcat。
3. Python
- HTTP 服务器:gunicorn、uWSGI、uvicorn
- 应用容器 / 规范:WSGI / ASGI
- 业务框架:Django、Flask、FastAPI结构:
浏览器 → gunicorn(HTTP服务器) → WSGI → Flask/Django
对应 Java:
- gunicorn ≈ Tomcat Connector
- WSGI ≈ Servlet 规范
- Flask ≈ SpringMVC
4. PHP
- HTTP 服务器:Nginx、Apache
- 应用运行器:php-fpm
- 业务:PHP 代码结构:
浏览器 → Nginx → php-fpm → PHP脚本
- Nginx 做 HTTP 解析
- php-fpm 负责运行 PHP、管理进程 / 线程
5. Node.js
- HTTP 服务器:Node 内置 http 模块
- 框架:Express、Koa、NestJS结构:
浏览器 → Node内置HTTP → Express路由 → 接口
和 Go 很像:自带 HTTP 服务器,不需要外置容器。
核心规律(非常重要)
所有语言 Web 架构,本质只有两种模式:
模式 1:自带 HTTP 服务器(Go、Node、SpringBoot 内嵌)
- HTTP 服务器直接嵌在进程里
- 一个进程跑完全部
- 代表:
- SpringBoot 内嵌 Tomcat
- Go net/http
- Node http
就是你现在项目的样子:一个 Java 进程全包。
模式 2:HTTP 服务器与应用分离(传统 PHP、Python、Java 外置 Tomcat)
浏览器 → Nginx/Apache → 应用容器 → 代码
- Nginx 只管 HTTP
- 后面容器只管业务
回到你最疑惑的点:为什么 Java 要搞 Servlet 容器?
因为历史 + 规范:
- Java 很早就定了 Servlet 规范
- 把「业务运行」和「HTTP 网络」强行拆成两层
- Tomcat 把两层都实现了,所以它既是 HTTP 服务器,又是 Servlet 容器
其他语言没有统一规范,就自己随便组合:
- Go:自带 HTTP + 框架
- Python:HTTP 服务器 (gunicorn) + WSGI 规范 + 框架
- PHP:Nginx + php-fpm
思想完全一样,只是名字不同。
用最简单的话总结(你记这个就够)
- HTTP 服务器:所有语言都有,负责 TCP、HTTP、网络,通用
- 应用容器 / 运行器:语言专属,负责跑业务代码
- Tomcat 特殊在:它同时包含 HTTP 服务器 + Servlet 容器
- 其他语言只是拆成不同组件,架构逻辑一模一样
Java 外置 Tomcat,项目跑起来的时候有几个进程
Java 外置 Tomcat 和 SpringBoot 内嵌,进程数量完全不一样,这是面试和部署最容易搞混的点。
一句话结论
- 外置 Tomcat(传统方式,把 war 丢进 webapps)→ 1 个 Tomcat 进程,里面可以跑多个 Java 项目
- SpringBoot 内嵌 Tomcat(jar 方式)→ 1 个项目 = 1 个独立 Java 进程
一、外置 Tomcat 启动时:几个进程?
你平时这种玩法:
- 下载 apache-tomcat-xxx.zip
- startup.bat/startup.sh 启动 Tomcat
- 把你的项目打成 war 包 丢进
webapps
启动后:
- 操作系统里 只有 1 个 Java 进程:tomcat 自己
- 你的项目 不是独立进程,是跑在 Tomcat 内部的
操作系统
└── 1 个 Java 进程(Tomcat)
├── 你的项目A(war1)
├── 项目B(war2)
└── 项目C(war3)
所以:项目跑起来,仍然只有 1 个进程(Tomcat 进程)。
二、那它和内嵌 Tomcat 区别到底在哪?(重点)
1. 内嵌(SpringBoot jar)
java -jar app.jar- → 启动 1 个 JVM 进程
- → 里面自己 new 了一个 Tomcat
- 一个项目 = 一个进程
2. 外置(传统 war 部署)
- 先启动
tomcat/bin/startup.sh - → 启动 1 个 JVM 进程
- 然后你丢 N 个 war 进去
- → N 个项目 共用 同一个 Tomcat 进程
最核心区别:
- 内嵌:项目自带 Tomcat,独立进程,隔离性好
- 外置:多个项目共用一个 Tomcat 进程,不隔离
三、外置 Tomcat 内部结构(一眼看懂)
Tomcat JVM 进程
├── Server / Service
├── Connector(监听8080)
├── Engine
│ ├── Host
│ │ ├── Context1 → 项目A war
│ │ ├── Context2 → 项目B war
│ │ └── Context3 → 项目C war
- 每个 war = 一个
Context - 所有 Context 共用同一个 JVM、同一个堆内存、同一个 Tomcat 线程池
四、请求怎么处理?(和你之前知识串起来)
- 浏览器请求进来
- Tomcat Connector(HTTP 服务器)接收
- 根据 URL 找到对应 Context(你的项目)
- 进入该项目的
DispatcherServlet - 执行 Controller
- 返回响应
全程都在 同一个 Tomcat 进程 里。
五、你最容易懵的 3 个问题,直接答死
1. 外置 Tomcat 跑 3 个项目,有几个进程?
1 个进程(Tomcat)
2. 一个项目挂了,会影响其他项目吗?
会!因为共用一个 JVM:
- 某个项目 OOM
- 直接把整个 Tomcat 搞崩
- 所有项目一起挂👉 这就是为什么现在都用 SpringBoot 独立部署。
3. 外置 Tomcat 里,项目是进程吗?
不是。项目只是 Tomcat 里的 一组 Class + 一组 Bean + 一个 Context,不是进程。
六、极简总结(背这个)
- 外置 Tomcat:1 个进程,多项目共享
- 内嵌 Tomcat:1 个项目 = 1 个独立进程
- 线程模型、HTTP 服务器、Servlet 容器原理完全一样,只是进程模型不同
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)