web.xml中servlet-mapping路径匹配严格按优先级:精确匹配>前缀匹配(/xxx/)>扩展名匹配(.xxx)>默认匹配(/);/与/*完全不同,前者为默认servlet,后者覆盖全部导致静态资源404;注解与xml配置互斥,须统一使用一种方式。

web.xml 中 servlet-mapping 的路径匹配到底怎么写才生效
不加斜杠、加斜杠、带星号,三种写法行为完全不同,不是“差不多能用”——写错就 404 或全拦住。
关键看两点:是否以 / 开头、结尾是否有 *。容器按「精确匹配 → 前缀匹配(/xxx/*)→ 扩展名匹配(*.xxx)→ 默认匹配(/)」顺序找,只取第一个命中项。
-
<url-pattern>/api</url-pattern>:只匹配/api,不匹配/api/或/api/users -
<url-pattern>/api/*</url-pattern>:匹配/api、/api/、/api/users、/api/v1/anything,但注意:request.getServletPath()截到/api,后面是getPathInfo() -
<url-pattern>*.do</url-pattern>:匹配任意路径下以.do结尾的请求,如/user/login.do,但不能写成/xxx/*.do—— 扩展名匹配不允许路径前缀
为什么 / 和 /* 看起来像却完全不是一回事
/ 是“默认 Servlet”,处理所有没被其他 pattern 拦下的请求(比如静态资源),而 /* 是“覆盖全部”,连 .jsp、/favicon.ico 都会进你的 Servlet —— 这是线上最常导致静态资源打不开或 JSP 不解析的元凶。
典型翻车现场:<url-pattern>/*</url-pattern> 配给 Spring DispatcherServlet,结果 CSS/JS 404,JSP 直接下载。
立即学习“Java免费学习笔记(深入)”;
- 想让 Servlet 处理所有路径但保留静态资源?别用
/*,改用/app/*+ 前端路由或反向代理剥离 - 真要接管全部?确保你自己能处理
GET /favicon.ico和HEAD /health这类探测请求 - Tomcat 9+ 对
/*的处理更严格,某些情况会直接拒绝部署
多个 servlet-mapping 共存时谁优先
不是按 XML 里写的顺序,而是严格按规范定义的匹配优先级:精确 > 前缀 > 扩展名 > 默认。哪怕你把 *.html 写在最上面,只要有个 /user/profile 精确匹配,它就永远先中。
常见误判:<url-pattern>/user/*</url-pattern> 和 <url-pattern>/user/login.html</url-pattern> 同时存在,后者永远不会触发 —— 因为 /user/login.html 先被前缀匹配吃掉了。
- 扩展名匹配(
*.jsp)和前缀匹配(/admin/*)冲突时,前缀赢 - 两个前缀匹配,长的优先:
/api/v2/*比/api/*优先 - 完全一样的 pattern,不同 servlet,容器行为未定义,别这么干
Servlet 3.0+ 注解方式下,web.xml 还要不要配 servlet-mapping
如果用了 @WebServlet(urlPatterns = "/api"),且没有设置 metadata-complete="true",web.xml 里的 mapping 就会被忽略 —— 但反过来,如果 web.xml 里写了 mapping,注解就失效了。
混合使用极易失控:比如注解写了 @WebServlet("/v1/*"),web.xml 又配了个 /v1/user,结果只有 web.xml 生效,你还以为注解漏写了。
- 二选一:纯注解就删掉 web.xml 中所有
servlet和servlet-mapping;纯 XML 就删掉所有@WebServlet - 想保留 web.xml 做环境差异化配置?把注解全去掉,统一收口
- Spring Boot 默认禁用 web.xml,
spring.mvc.servlet.path控制的是 DispatcherServlet 的 base path,和这里不是同一层
路径映射看着简单,实际是请求入口的闸门。一个斜杠位置不对,整个流量就拐错了弯,而且问题往往不报错,只静默失效。










