Mapper 路由与 Pipeline/Valve
Mapper 负责请求落到哪个容器,Pipeline/Valve 负责请求经过哪些处理步骤。
先给答案:Mapper 负责“找到对象”,Valve 负责“按容器链执行对象”
Section titled “先给答案:Mapper 负责“找到对象”,Valve 负责“按容器链执行对象””URI 映射需要在 Host、Context、Wrapper 多级命名空间中查找,Mapper 把结果压缩成可执行的映射;随后 Pipeline/Valve 负责认证、日志、错误处理和最终调用。查找与执行分离,才能让映射规则变化不必重写整个请求处理链。
映射失败、重定向、静态资源和 Servlet 匹配也因此属于不同分支。排查 404 时先判断请求有没有找到 Context/Wrapper,再判断 Valve 是否执行、Servlet 是否返回 404,不能把所有“找不到”都归为同一层。
host + URI -> Mapper#map -> Engine/Host/Context/Wrapper -> EngineValve -> HostValve -> ContextValve -> WrapperValveMapper#map 位于 java/org/apache/catalina/mapper/Mapper.java:688,内部查找从 :730 开始;映射表通过 insertMap/removeMap(:1480、:1495)更新。StandardEngineValve#invoke 位于 java/org/apache/catalina/core/StandardEngineValve.java:54,:71 进入 Host;Host、Context、Wrapper Valve 分别从 StandardHostValve.java:78、StandardContextValve.java:54、StandardWrapperValve.java:84 开始。
为什么查找和执行分离
Section titled “为什么查找和执行分离”替代方案:每个 Valve 自己遍历子容器并匹配 URI。 为什么不行:路由算法和执行策略耦合后,通配路径、并发更新和自定义 Valve 会互相污染。Mapper 专门优化查找,Valve 专门实现认证、日志、访问控制和 Servlet 调用。
| 场景 | 现象 | 原因 | 规避 |
|---|---|---|---|
| Host 头异常 | 命中默认 Host | Host 映射失败 | 明确 defaultHost |
| Context 歧义 | 命中错误应用 | 路径匹配或版本选择错误 | 检查部署命名 |
| Valve 不调用 next | 请求链中断 | 自定义 Valve 提前返回 | 明确短路条件 |
| 动态更新路由 | 短时旧视图 | 映射表快照切换 | 正确发布顺序 |
不可变快照读加受控写切换适合路由表和规则引擎;前置/后置责任链适合认证、审计和限流。
面试锚点
- Mapper 和 Pipeline 分别解决什么问题?
- Host、Context、Wrapper 如何命中?
- 自定义 Valve 忘记调用 next 会怎样?