web.xml 配置详解
本章定位 :理解 web.xml 作为 Java Web 应用部署描述符的结构——Servlet/Filter/Listener 注册、URL 映射模式、加载顺序和 Jakarta EE 版本变迁。
定义与作用
web.xml 是 Java Web 应用(WAR 包)的 部署描述符 (Deployment Descriptor),放在 WEB-INF/ 目录下。它告诉 Servlet 容器(Tomcat/Jetty)如何加载和配置这个 Web 应用。
web.xml 通过纯 XML 声明来定义:
- 哪些 Servlet 处理哪些 URL
- 哪些 Filter 在请求前后执行
- 应用启动时触发哪些 Listener
- 欢迎页面、错误页面、Session 超时等配置
核心原理:Servlet 容器启动加载流程
图解释 :Servlet 容器按固定顺序加载 web.xml:Listener → context-param → Filter → Servlet。load-on-startup 控制 Servlet 是启动时加载还是第一次请求时加载。请求到达后经过 Filter 链(类似 Java Web 中的"拦截器管道")再到目标 Servlet。
语法/结构要点
标准 web.xml 骨架
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<!-- display-name -->
<!-- context-param * -->
<!-- listener * -->
<!-- filter * + filter-mapping * -->
<!-- servlet * + servlet-mapping * -->
<!-- welcome-file-list -->
<!-- error-page * -->
<!-- session-config -->
</web-app>
核心配置项
| 元素 | 作用 | 示例 |
|---|---|---|
context-param | 全局初始化参数 | 数据库连接字符串 |
listener | 注册监听器 | ContextLoaderListener |
filter + filter-mapping | 过滤器及 URL 映射 | 编码过滤器 /* |
servlet + servlet-mapping | Servlet 及 URL 映射 | /api/* |
welcome-file-list | 默认首页 | index.html |
error-page | 错误页面映射 | 404 → /error404.html |
session-config | Session 超时(分钟) | <session-timeout>30</session-timeout> |
URL 映射模式
| 模式 | 示例 | 匹配 |
|---|---|---|
| 精确匹配 | /login | 仅 /login |
| 路径匹配 | /api/* | /api/user, /api/order |
| 扩展名匹配 | *.do | /user.do, /order.do |
| 默认匹配 | / | 所有未匹配的请求 |
完整示例:白歌配置飞翔科技教学管理系统
场景说明
飞翔科技的架构师 白歌 为新项目"在线教学管理系统"编写 web.xml。需求:字符编码过滤、登录 Servlet、REST API DispatcherServlet、404 错误页面、30 分钟超时。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<display-name>飞翔科技教学管理系统</display-name>
<!-- 全局参数 -->
<context-param>
<param-name>appName</param-name>
<param-value>FeixiangEdu</param-value>
</context-param>
<context-param>
<param-name>logLevel</param-name>
<param-value>INFO</param-value>
</context-param>
<!-- 监听器:Spring 上下文加载 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- Filter 1:字符编码(最先执行) -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Filter 2:认证检查 -->
<filter>
<filter-name>authFilter</filter-name>
<filter-class>
com.feixiang.edu.filter.AuthFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>authFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
<!-- Servlet 1:登录 Servlet(启动时加载) -->
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>
com.feixiang.edu.servlet.LoginServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<!-- Servlet 2:Spring MVC DispatcherServlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!-- 欢迎页面 -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 错误页面 -->
<error-page>
<error-code>404</error-code>
<location>/errors/404.html</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/errors/500.html</location>
</error-page>
<!-- Session 配置 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
操作结果
容器启动时的加载顺序:
ContextLoaderListener初始化 Spring 根上下文encodingFilter注册到/*(所有请求先过编码过滤器)authFilter注册到/admin/*(管理页面需要认证)loginServlet实例化(load-on-startup=1)dispatcher实例化(load-on-startup=2)
请求 /admin/courses 的流转:encodingFilter → authFilter → dispatcher(/api/*不匹配→404) — 请求 /api/courses:encodingFilter → dispatcher → Controller。
易错场景
错误一:filter-mapping 顺序就是执行顺序
web.xml 中 filter-mapping 的声明顺序决定了 Filter 链的执行顺序。编码过滤器必须放在最前面,否则后续过滤器拿到的可能是乱码。
错误二:忘记设置 load-on-startup
不设置 load-on-startup 时,Servlet 在 第一次请求 时才实例化。如果 Servlet 初始化耗时(如加载模型),第一个用户会"卡住"。设为 ≥ 0 的值让容器启动时预加载。
面试考点
| 考点 | 参考答案要点 |
|---|---|
| web.xml 中元素的加载顺序? | Listener → context-param → Filter(按 mapping 声明顺序)→ Servlet(load-on-startup 升序,未设置的按需加载) |
| Filter 链的执行机制? | 每个 Filter 的 doFilter() 调用 chain.doFilter() 传递到下一个,最后到达 Servlet。响应沿反向链返回 |
| load-on-startup 的作用? | 控制 Servlet 加载时机:≥0 时容器启动即加载(数值越小越早),不设置或负数则第一次请求时加载 |