首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Web Servlet 基礎配置詳解:web.xml 映射規則與容器匹配邏輯

     編輯:Java 相關知識

Servlet 是 Java Web 核心組件,`web.xml` 中的 `` 與 `` 配置決定了請求如何路由到 Servlet。本文系統講解基礎配置、三種 URL 模式、容器匹配優先級、常見錯誤與最佳實踐,附帶 Spring Boot 時代的對比說明。

一、最小化配置示例

<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee"
         version="3.1">

    <!-- 1. Servlet 定義:名稱 + 完全限定類名 -->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.example.servlet.MyServlet</servlet-class>
    </servlet>

    <!-- 2. 映射規則:Servlet 名稱 + URL 模式 -->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/api/users</url-pattern>
    </servlet-mapping>

</web-app>

二、兩大核心元素詳解

元素子元素作用關鍵點
<servlet><servlet-name>邏輯名稱,供 mapping 引用自定義,建議有語義
<servlet-class>完全限定類名必須實現 Servlet 接口/繼承 HttpServlet
<init-param>初始化參數ServletConfig.getInitParameter() 獲取
<load-on-startup>啟動加載順序≥0 整數,數值小先加載
<servlet-mapping><servlet-name>引用 servlet 定義必須與定義一致
<url-pattern>URL 匹配規則核心路由邏輯,見下文

三、三種 URL Pattern 類型

類型語法示例匹配示例用途
精確匹配以 `/` 開頭,無通配符`/api/users`僅 `/api/users`REST 端點、固定路徑
路徑匹配以 `/` 開頭,以 `/*` 結尾`/api/*`、`/*``/api/users`、`/api/orders/123`、`/any/path`前綴路由、前端控制器
擴展匹配以 `*.` 開頭`*.do`、`*.action`、`*.json``submit.do`、`/path/to/action.do`傳統框架、靜態資源區分
> ⚠️ **禁止混合**:`/*.do` 同時屬於路徑匹配和擴展匹配,容器無法判斷,導致部署失敗或行為未定義。

四、容器匹配優先級(Servlet Spec 12.2)

當請求進入容器,按以下順序查找,**首個匹配生效**:

  1. 精確匹配:`requestURI == url-pattern`
  2. 最長路徑匹配:`requestURI` 以 `url-pattern` 去掉 `/*` 的前綴開頭,選擇**最長前綴**者
  3. 擴展匹配:`requestURI` 以 `url-pattern` 去掉 `*.` 的後綴結尾
  4. 默認 Servlet:`url-pattern` 為 `/`,處理靜態資源、未匹配請求

優先級示例

<servlet-mapping>
    <servlet-name>ServletA</servlet-name>
    <url-pattern>/test/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>ServletB</servlet-name>
    <url-pattern>/test/b/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>ServletC</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>
| 請求路徑 | 匹配結果 | 原因 | |----------|----------|------| | `/test/b/c` | **ServletB** | 最長路徑匹配(`/test/b/` > `/test/`) | | `/test/a` | **ServletA** | 路徑匹配 `/test/*` | | `/test/b.action` | **ServletC** | 擴展匹配 `*.do` 不匹配,無 `.do` 後綴 → 404 或默認 Servlet | | `/test/b.do` | **ServletC** | 擴展匹配 `*.do` 生效(路徑匹配優先級高於擴展,但 `/test/b.do` 不以 `/test/` 開頭?實際:`/test/b.do` 以 `/test/` 開頭,**路徑匹配優先** → ServletA) | > **關鍵結論**:路徑匹配優先級**高於**擴展匹配。`/test/b.do` 會匹配 `/test/*`(ServletA),而非 `*.do`(ServletC)。這是 Servlet 規範設計為「目錄結構優於文件類型」。

五、常見錯誤與避坑

錯誤現象修正
`servlet-name` 不一致404、ClassNotFound、映射失效定義與映射名稱完全一致
`url-pattern` 寫成 `*.action` 但請求帶路徑`/user/save.action` 匹配 `*.action` 正常,但 `/user/save` 不匹配按需選擇路徑匹配或擴展匹配
同一 Servlet 多 mapping 衝突不可預期行為一個 Servlet 對應一個 mapping,複雜路由用 Filter/前端控制器
忽略 `load-on-startup`首次請求慢(初始化延遲)核心 Servlet 設定 `1` 或更小
Servlet 3.0+ 註解與 web.xml 混用衝突重複註冊、覆蓋二選一:傳統項目用 web.xml,現代項目用 `@WebServlet`

六、Servlet 3.0+ 註解配置(現代標準)

@WebServlet(
    name = "MyServlet",
    urlPatterns = { "/api/users", "/api/users/*" },
    initParams = {
        @WebInitParam(name = "pageSize", value = "20"),
        @WebInitParam(name = "encoding", value = "UTF-8")
    },
    loadOnStartup = 1,
    asyncSupported = true  // 支援異步處理
)
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        // 業務邏輯
    }
}
  • 無需 `web.xml`,容器掃描類路徑自動註冊。
  • `metadata-complete="true"` 可禁用掃描加速啟動。

七、Spring Boot 時代的 Servlet 註冊

Spring Boot 不使用 `web.xml`,提供三種註冊方式:

  1. ServletRegistrationBean(推薦):
    @Bean
    public ServletRegistrationBean myServlet() {
        ServletRegistrationBean bean = new ServletRegistrationBean<>(new MyServlet(), "/api/users/*");
        bean.setLoadOnStartup(1);
        bean.addInitParameter("encoding", "UTF-8");
        return bean;
    }
  2. @ServletComponentScan + @WebServlet:掃描註解自動註冊。
  3. web.xml(兼容模式):`src/main/webapp/WEB-INF/web.xml`,需 `spring.servlet.register-default-servlet=true`。

八、最佳實踐總結

  1. 新項目**優先使用 `@WebServlet` 註解**,簡潔、類型安全、IDE 重構友好。
  2. 傳統項目維護 `web.xml` 時,遵循「精確 > 最長路徑 > 擴展」優先級設計映射。
  3. 避免 `/*.do` 混合模式,路徑匹配用 `/api/*`,擴展匹配用 `*.do`,二者互斥。
  4. 核心業務 Servlet 設置 `load-on-startup=1`,減少首請求延遲。
  5. Spring Boot 項目用 `ServletRegistrationBean` 程序化註冊,集中管理、易於測試。
  6. 複雜路由(REST、版本、多租戶)交給 **Spring MVC `@RequestMapping`** 或 **Filter 鏈** 處理,Servlet 僅作入口。

理解 Servlet 映射機制,是排查 404、請求不到 Controller、靜態資源攔截等問題的關鍵。從 `web.xml` 到註解再到 Spring Boot 自動配置,本質邏輯不變:**名稱綁定類、模式匹配路徑、優先級決定勝負**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved