Tomcat 中 Host、Context、Context Path 和 WAR 包是什么关系?
简化版
Host 是虚拟主机,对应一个域名(如 www.a.com);Context 是一个 Web 应用(Tomcat 管理 Web 应用的单位,有独立的 ServletContext、类加载器、会话);Context Path 是这个应用在 URL 中的访问前缀(如 /shop);WAR 包 是 Web 应用的打包形式(Web Application Archive)。关系:把 WAR 放进 Tomcat 的 webapps 目录,Tomcat 会解压并为它创建一个 Context,Context Path 默认由 WAR 文件名决定(shop.war → /shop,ROOT.war → 根路径 /)。同一个 Host 下可以有多个 Context(多个应用),不同 Host 按域名区分。
详细版
四个概念的层级关系:
Host(虚拟主机 www.a.com)
├─ Context 1(应用 shop) → Context Path: /shop ← 来自 shop.war
├─ Context 2(应用 blog) → Context Path: /blog ← 来自 blog.war
└─ Context 3(ROOT 应用) → Context Path: /(根) ← 来自 ROOT.war
| 概念 | 是什么 | 例子 |
|---|---|---|
| Host | 虚拟主机 / 域名 | www.example.com |
| Context | 一个 Web 应用(部署单位) | shop 应用 |
| Context Path | 应用在 URL 中的前缀 | /shop |
| WAR | Web 应用的打包文件 | shop.war |
WAR 文件名 → Context Path 的默认映射:
shop.war→ 解压成shop目录 → Context Path/shop,访问/shop/orders。ROOT.war→ Context Path/(根),访问/orders。- 也可用
context.xml/server.xml显式指定path和docBase。
完整版教学
一、Host:虚拟主机(按域名分应用)
Host 对应一个域名 / 虚拟主机(如 www.example.com)。一个 Tomcat 可以配置多个 Host,实现虚拟主机——让不同域名映射到不同的应用集合。
比如同一台 Tomcat 上,www.shop.com 走 Host A(下面挂电商应用),www.blog.com 走 Host B(下面挂博客应用)。请求来时,Tomcat 根据 HTTP 请求头里的 Host(域名)先定位到对应的 Host,再往下找应用。这是 Tomcat 四级容器(Engine → Host → Context → Wrapper)里的第二级。
二、Context:一个 Web 应用(部署单位)
Context 是 Tomcat 管理一个 Web 应用的单位。部署一个应用,本质就是创建并启动一个 Context。 每个 Context 拥有:
- 独立的 ServletContext(应用的全局上下文对象)。
- 独立的 类加载器(WebappClassLoader)——所以不同应用的依赖版本互相隔离(见 Tomcat 类加载专题)。
- 独立的 Session 管理、资源目录(
WEB-INF等)、Servlet/Filter 集合。
一个 Host 下可以有多个 Context(部署多个应用)。Context 是应用隔离的边界。
三、Context Path:URL 中的应用前缀
Context Path 决定用户访问 URL 里的应用前缀。例如访问 http://www.a.com/shop/orders:
www.a.com→ 定位 Host。/shop→ 这是 Context Path,定位到 shop 这个 Context(应用)。- 剩下的
/orders→ 交给应用内部的 Servlet / Spring MVC 路由处理。
所以 Context Path 是「域名之后、应用内部路径之前」的那一段,用来区分同一 Host 下的不同应用。
| URL 片段 | Tomcat 层级 | 例子 | 说明 |
|---|---|---|---|
| 域名 | Host | www.a.com | 先按 Host 请求头定位虚拟主机 |
| 应用前缀 | Context Path | /shop | 定位到某个 Web 应用 Context |
| 应用内路径 | Servlet/Spring 路由 | /orders | 进入应用后再匹配 Servlet 或 Controller |
http://www.a.com/shop/orders/123
|---------| |---| |---------|
Host Context 应用内路径
Path
记忆钩子:Host 决定“哪个域名的院子”,Context Path 决定“院子里的哪栋楼”,后面的路径才是应用内部房间号。
四、WAR 包与 Context Path 的默认关系
WAR(Web Application Archive) 是 Web 应用的标准打包格式(本质是个 zip,包含 WEB-INF/classes、WEB-INF/lib、静态资源等)。
把 WAR 放进 Tomcat 的 webapps 目录,Tomcat 会自动部署:
- 解压 WAR:
shop.war解压成shop目录。 - 创建 Context:为这个应用创建一个 Context。
- Context Path 默认取 WAR 文件名:
shop.war→ Context Path/shop,访问路径/shop/...。
也可以不依赖文件名,通过 context.xml 或 server.xml 里的 <Context path="..." docBase="..."> 显式指定 Context Path 和应用目录,更灵活可控(生产推荐显式配置而非依赖文件名)。
举个部署例子:同一个 Host 下放入 shop.war、blog.war、ROOT.war 3 个包,Tomcat 默认会创建 3 个 Context。它们分别对应 /shop、/blog、/。如果把 shop.war 改名成 shop-v2.war,默认路径会变成 /shop-v2,原来的 /shop/orders 就会 404,除非你显式配置 Context Path。
五、ROOT 应用的特殊性
有一个特殊的应用名 ROOT:ROOT.war(或 webapps/ROOT 目录)对应根路径 /,没有额外的 Context Path。访问 http://www.a.com/orders(不带应用前缀)就直接进入 ROOT 应用。
生产部署常把主应用部署为 ROOT——如果一个 Tomcat 只跑一个站点,部署成 ROOT 就能让 URL 少一层应用名(用 /orders 而不是 /shop/orders),更简洁、对 SEO 和用户更友好。
六、部署时的常见坑
- 改 WAR 文件名会改变默认 Context Path:
shop.war改名mall.war,访问路径就从/shop变成/mall——上线时改错文件名会导致路径全变、404。 - 同一 Host 下不能有两个相同的 Context Path:两个应用都想用
/shop会冲突。 server.servlet.context-path与外部 Context Path 叠加:Spring Boot 内嵌 Tomcat 时,server.servlet.context-path=/api会给应用再加一层前缀。如果又用外部 Tomcat 部署 WAR、外部也有 Context Path,两层会叠加,导致实际路径和预期不一致——这是路径 404 的常见原因。
七、和反向代理的关系(排查 404 的三层)
生产环境前面通常有 Nginx / 网关做反向代理,它可能对路径做 rewrite(如把外部的 /app/xxx 转发到 Tomcat 的 /xxx)。所以:外部访问路径 ≠ Tomcat 内部的 Context Path。
排查 404 要分三层看:
- 代理层:Nginx/网关的 location 匹配和 rewrite 规则,外部路径转成了什么。
- Tomcat 层:Context Path 是什么,请求进到了哪个应用。
- 应用层:应用内部的 Servlet mapping / Spring 路由是否匹配。
三层任何一层路径对不上都会 404。把它们分开看,比只怀疑业务代码快得多。
八、常见误区与追问
- 误区:WAR 文件名和访问路径完全无关。 默认自动部署时,WAR 文件名会决定 Context Path,
ROOT.war才对应根路径/。 - 误区:Context 就是 Controller 路由。 Context 是 Tomcat 的 Web 应用边界,Controller 路由是进入应用之后由框架处理的内部路径。
- 追问:为什么同一个 Host 下不能有两个相同 Context Path? Context Path 用来在同一域名下唯一定位应用,重复会让请求无法明确落到哪个 Context。
- 追问:Spring Boot 的
server.servlet.context-path和外部 WAR path 会怎样? 可能形成路径叠加,外部 Context Path 加上应用内部 context-path,导致实际 URL 比预期多一层。 - 误区:生产 404 一定是 Controller 没写对。 还可能是代理 rewrite 错、Tomcat Context Path 错、WAR 名称变化或 Servlet mapping 没匹配。
- 追问:为什么主站常部署成 ROOT? ROOT 对应根路径
/,URL 不带额外应用名前缀,路径更简洁。
九、加强记忆
Host(虚拟主机,对应域名)→ Context(一个 Web 应用,Tomcat 部署单位,有独立 ServletContext/类加载器/Session)→ Context Path(应用在 URL 中的前缀,如 /shop);WAR 是 Web 应用打包文件。放 WAR 到 webapps,Tomcat 解压并创建 Context,Context Path 默认取 WAR 文件名(shop.war→/shop,ROOT.war→根路径 /),也可 context.xml 显式指定 path/docBase。访问 www.a.com/shop/orders = Host(www.a.com) + Context Path(/shop) + 应用内路径(/orders)。坑:改 WAR 名会改路径、同 Host 不能有相同 path、Spring context-path 与外部会叠加。排查 404 分三层:代理 rewrite → Tomcat Context → 应用路由。