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

Java Web 入門必讀:Servlet 核心原理、生命週期與部署配置詳解

     編輯:Java 相關知識

前言:Servlet 是 Java Web 的「廚師」

Web 服務器本質是「請求-處理-響應」。Servlet 容器負責管理 Servlet 實例生命週期、解析 HTTP 請求、調度線程調用 `service/doGet/doPost`。本文從架構角色、核心介面、編譯部署、初始化流程、線程模型五個維度,建立 Servlet 完整認知框架。

一、架構角色定位


Client (Browser) 
    │ HTTP Request
    ▼
Web Server (Tomcat: Coyote HTTP/1.1 Connector)
    │ 解析請求 → HttpServletRequest
    ▼
Servlet Container (Catalina)
    │ 查找/創建 Servlet 實例
    │ 分配線程 → service(req, resp)
    ▼
Servlet Instance (你的業務類)
    │ 業務邏輯 → 操作 req/resp
    ▼
Servlet Container
    │ 根據 HttpServletResponse 生成 HTTP Response
    ▼
Web Server → Network → Client

二、核心介面體系

介面/類包角色關鍵方法
`Servlet``javax.servlet`核心契約`init()`, `service()`, `destroy()`, `getServletConfig()`, `getServletInfo()`
`GenericServlet``javax.servlet`協議無關基類實現 `Servlet`、`ServletConfig`,簡化 `init`/`destroy`
`HttpServlet``javax.servlet.http`HTTP 專用基類`doGet()`, `doPost()`, `doPut()`, `doDelete()`, `service()` 分發
`HttpServletRequest``javax.servlet.http`請求封裝參數、Header、Cookie、Session、屬性、輸入流
`HttpServletResponse``javax.servlet.http`響應封裝狀態碼、Header、Cookie、輸出流、重定向
`ServletConfig``javax.servlet`單個 Servlet 配置`getInitParameter()`, `getServletName()`, `getServletContext()`
`ServletContext``javax.servlet`Web 應用全局上下文`getInitParameter()`, `getAttribute()`, `getResourceAsStream()`, `getRequestDispatcher()`

三、生命週期:三大關鍵時刻

  1. 實例化與初始化:容器創建實例 → 調用 `init(ServletConfig config)`(僅一次)。可在 `init` 中讀取初始化參數、建立連接池、載入配置。
  2. 請求服務:每請求分配線程 → 調用 `service(req, resp)` → `HttpServlet` 分發到 `doGet/doPost` 等。**同一實例服務多請求,必須線程安全。**
  3. 銷毀:容器關閉/重新部署 → 調用 `destroy()`(僅一次)。釋放資源:關閉連接池、線程池、緩存、文件句柄。

生命週期圖解


[類加載] → [實例化 new Servlet()] → [init(config)] ──→ [服務中...] ──→ [destroy()] → [卸載]
                │                          ▲                    │
                │                          │                    │
                └────────── 單例 ──────────┘                    │
                       (多線程共享實例)                         │
                                        (容器關閉/重載)

四、部署配置:從 web.xml 到註解

4.1 傳統 web.xml (Servlet 2.5/3.0 兼容)



    
        TimeServlet
        com.example.TimeServlet
        
            timezone
            GMT+8
        
        1 
    
    
        TimeServlet
        /time
    

4.2 註解配置 (Servlet 3.0+,主流)


@WebServlet(
    name = "TimeServlet",
    urlPatterns = {"/time", "/current-time"},
    initParams = {
        @WebInitParam(name = "timezone", value = "GMT+8")
    },
    loadOnStartup = 1,
    asyncSupported = true // 支持異步處理
)
public class TimeServlet extends HttpServlet {
    @Override
    public void init(ServletConfig config) {
        String tz = config.getInitParameter("timezone");
        // 初始化邏輯
    }
    // ...
}

4.3 URL 模式匹配規則

模式示例匹配路徑
精確路徑`/api/users`僅 `/api/users`
目錄前綴`/api/*``/api/users`, `/api/orders/123`
擴展名`*.do`, `*.action``/login.do`, `/submit.action`
默認 Servlet`/`所有未匹配路徑 (靜態資源、SPA 入口)

五、線程模型與線程安全

  • 單實例多線程: 容器為每個請求分配線程(或從池取),調用同一 Servlet 實例的 `service()`。
  • 局部變量安全: `doGet` 內部定義的變量線程私有,安全。
  • 成員變量危險: `private User currentUser;` 多線程競爭覆蓋,**嚴禁**存儲請求狀態。
  • 共享資源同步: 連接池、緩存、計數器等共享對象需線程安全實現或同步。

線程安全最佳實踐


// ❌ 危險:成員變量存請求狀態
private String username;
public void doGet(...) { this.username = req.getParameter("u"); ... }

// ✅ 安全:局部變量
public void doGet(...) { String username = req.getParameter("u"); ... }

// ✅ 安全:請求屬性 (轉發鏈共享)
req.setAttribute("username", username);

// ✅ 安全:ThreadLocal (慎用,防洩漏)
private static final ThreadLocal currentUser = new ThreadLocal<>();
public void doGet(...) { currentUser.set(user); try {...} finally { currentUser.remove(); } }

六、初始化參數與上下文參數

範圍配置方式獲取 API用途
單 Servlet`` / `@WebInitParam``config.getInitParameter(name)`該 Servlet 專用配置 (如時區、頁面大小)
全 Web 應用```context.getInitParameter(name)`全局配置 (如資料庫 URL、上傳目錄、功能開關)

七、異步 Servlet (Servlet 3.0+)

長耗時操作 (遠程調用、推送、報表生成) 釋放容器線程,提升吞吐:


@WebServlet(urlPatterns = "/async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        AsyncContext ctx = req.startAsync(); // 開啟異步
        ctx.setTimeout(30000);
        
        new Thread(() -> {
            try {
                // 耗時業務
                Thread.sleep(5000);
                resp.setContentType("text/plain");
                resp.getWriter().write("Async Done");
            } catch (Exception e) { log.error(e); }
            finally { ctx.complete(); } // 完成響應
        }).start();
    }
}

結語

Servlet 看似簡單,實則蘊含「容器管理生命週期、單例多線程服務、請求響應封裝、配置與註解雙軌、同步與異步並存」等核心架構思想。徹底理解生命週期、線程模型、部署配置,是進階 Spring MVC、Spring WebFlux、Netty、gRPC 等框架的必經之路。下一篇將實戰《Filter 與 Listener:請求攔截鏈與應用生命週期監聽完全指南》。

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