web.xml 是 Servlet 規範定義的部署描述符,雖然 Spring Boot 推廣零配置,但理解其完整結構對維護舊項目、排查容器級問題、設計框架仍不可或缺。本文系統覆蓋 Servlet/Filter/Listener 註冊、URL 映射規則、初始化參數、錯誤頁面、Welcome 文件、會話配置、安全約束、資源引用。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee
https://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0" metadata-complete="true">
<!-- metadata-complete="true":跳過註解掃描,加快啟動 -->
...
</web-app>
<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>1</load-on-startup> <!-- 啟動時實例化,正整數越小越早 -->
<async-supported>true</async-supported> <!-- 支持異步 Servlet 3.0+ -->
<multipart-config> <!-- 文件上傳配置 3.0+ -->
<max-file-size>10485760</max-file-size>
<max-request-size>20971520</max-request-size>
<file-size-threshold>0</file-size-threshold>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern> <!-- 默認 Servlet,攔截所有含靜態資源 -->
</servlet-mapping>
/user/login/user/**.do, *.jsp/ (僅 DispatcherServlet 常用)<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>
<init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
<dispatcher>ASYNC</dispatcher> <!-- 3.0+ -->
</filter-mapping>
REQUEST:直接瀏覽器請求 (默認,僅配置 url-pattern 等同)FORWARD:RequestDispatcher.forward() 轉發請求INCLUDE:RequestDispatcher.include() 包含請求ERROR:錯誤頁面請求 (error-page 觸發)ASYNC:異步請求 (startAsync())最佳實踐:編碼/日誌/安全 Filter 配置 REQUEST,FORWARD,INCLUDE,ERROR,ASYNC 全覆蓋。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<listener>
<listener-class>com.app.listener.SessionCountListener</listener-class>
</listener>
| 接口 | 監聽事件 | 典型用途 |
|---|---|---|
| ServletContextListener | 應用啟動/銷毀 | 初始化全局資源、關閉線程池 |
| HttpSessionListener | Session 創建/銷毀 | 在線用戶統計 |
| ServletRequestListener | 請求開始/結束 | 請求耗時統計、MDC 設置 |
| ServletContextAttributeListener | Application 屬性增刪改 | 配置變更通知 |
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/error/500.jsp</location>
</error-page>
錯誤頁面中可用 exception 隱式對象 (isErrorPage="true")。
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>/index</welcome-file> <-- 可映射到 Servlet -->
</welcome-file-list>
<session-config>
<session-timeout>30</session-timeout> <!-- 分鐘,0/-1 永不過期 -->
<cookie-config> <!-- 3.0+ -->
<name>JSESSIONID</name>
<http-only>true</http-only>
<secure>false</secure> <!-- HTTPS 才 true -->
<max-age>1800</max-age>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode> <!-- COOKIE/URL/SSL -->
</session-config>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<resource-ref> <!-- 數據源 JNDI 引用 -->
<res-ref-name>jdbc/myDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<env-entry> <!-- 環境變量 -->
<env-entry-name>app/version</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>1.0.0</env-entry-value>
</env-entry>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin Area</web-resource-name>
<url-pattern>/admin/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>ADMIN</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee> <!-- 強制 HTTPS -->
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-error.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role><role-name>ADMIN</role-name></security-role>
| web.xml 配置 | 註解替代 | 備註 |
|---|---|---|
| <servlet> + <servlet-mapping> | @WebServlet(urlPatterns="/api/*") | 需啟用註解掃描 |
| <filter> + <filter-mapping> | @WebFilter(urlPatterns="/*") | dispatcherTypes 配置 dispatcher |
| <listener> | @WebListener | |
| <init-param> | @WebInitParam | |
| <multipart-config> | @MultipartConfig |
web.xml 是 Java Web 應用的「身份證與説明書」。即使現代框架推崇零配置,掌握其完整語義、映射規則、Dispatcher 類型、安全約束,仍是資深開發者排查部署異常、設計基礎設施的必備基本功。