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

Servlet 生命周期與調用流程全解析:從 HTTP 請求到響應的完整鏈路

     編輯:Java 綜合教學

Servlet 核心機制:生命周期、繼承體系與配置細節

Servlet 是 Java Web 開發的基石。理解其生命周期管理、請求處理流程與容器交互細節,是排查 Web 層問題、優化性能的前提。

一、Servlet 調用流程

  1. 瀏覽器發起 HTTP Request
  2. Web 容器 (Tomcat/Jetty) 解析請求行/頭/體,封裝為 HttpServletRequest
  3. 容器查找 web.xml (或註解) 中的 <servlet-mapping> 匹配 URL
  4. 若 Servlet 未初始化 → 實例化 → init()
  5. 容器創建 HttpServletResponse,調用 service(req, resp)
  6. service() 根據 HTTP 方法分發:doGet()/doPost()/…
  7. 業務邏輯處理,調用 resp.getWriter().write() 或 resp.getOutputStream() 輸出
  8. 容器將 Response 組裝為 HTTP 響應返回瀏覽器
  9. Web 應用卸載/容器關閉 → destroy()

二、生命周期三大核心方法

方法調用時機調用次數典型用途
init(ServletConfig)首次請求或啟動時 (load-on-startup)1 次加載配置、初始化連接池、緩存預熱
service(req, resp)每次請求N 次核心業務處理入口,HTTP 方法分發
destroy()容器卸載 Servlet 前1 次釋放資源、關閉連接、持久化狀態

關鍵點

  • 單例多線程:容器默認只創建一個 Servlet 實例,多線程並發調用 service()
  • 線程安全責任在開發者:不要在 Servlet 中定義實例變量存儲請求級數據
  • init() 拋異常 → Servlet 標記為不可用,後續請求直接 500

三、繼承體系架構

Servlet (Interface)
  │
  ├─ GenericServlet (抽象類)
  │     └─ service() 為抽象,需子類實現,協議無關
  │
  └─ HttpServlet (核心類)
        └─ 實現 service():解析 HTTP 方法 → 調用 doGet/doPost/doPut/doDelete...
             子類只需覆蓋對應 doXxx() 方法

HttpServlet 核心邏輯

protected void service(HttpServletRequest req, HttpServletResponse resp) {
    String method = req.getMethod();
    if ("GET".equalsIgnoreCase(method)) {
        doGet(req, resp);
    } else if ("POST".equalsIgnoreCase(method)) {
        doPost(req, resp);
    } // ... HEAD, PUT, DELETE, OPTIONS, TRACE
    // 不支持的方法返回 405
}

四、Request/Response 核心契約

對象來源核心內容典型用法
HttpServletRequest容器創建請求行、Headers、Parameters、Body、Session、AttributesgetParameter(), getInputStream(), getSession()
HttpServletResponse容器創建 (空對象)Status、Headers、Body (Writer/OutputStream)setContentType(), getWriter(), sendRedirect()

五、web.xml 映射規則與優先級

<servlet>
    <servlet-name>demo</servlet-name>
    <servlet-class>com.demo.DemoServlet</servlet-class>
    <load-on-startup>1</load-on-startup> <!-- 啟動順序,數值越小越早 -->
</servlet>

<servlet-mapping>
    <servlet-name>demo</servlet-name>
    <url-pattern>/api/*</url-pattern> <!-- 路徑映射 -->
</servlet-mapping>

URL Pattern 匹配優先級 (高 → 低)

  1. 精確匹配:/api/user
  2. 路徑前綴匹配:/api/*
  3. 擴展名匹配:*.do, *.action
  4. 默認 Servlet:/ (最低優先級)

原則:誰最具體用誰。一個 <servlet> 可映射多個 <servlet-mapping>。

六、Servlet 3.0+ 註解配置 (無 web.xml)

@WebServlet(
    name = "demo",
    urlPatterns = {"/api/*", "/demo"},
    loadOnStartup = 1,
    initParams = {@WebInitParam(name="key", value="value")},
    asyncSupported = true  // 支持異步處理
)
public class DemoServlet extends HttpServlet { ... }

七、常見陷阱與最佳實踐

陷阱後果正確做法
Servlet 實例變量存請求數據併發數據混亂使用局部變量、ThreadLocal、Request 屬性
init() 耗時長阻塞啟動應用啟動超時異步初始化、延遲加載、load-on-startup 排序
不關閉輸出流連接洩漏、客戶端收不到完整響應try-with-resources 或 finally 關閉
直接操作 Session 併發屬性覆蓋/丟失Session 非線程安全,同步塊或 ConcurrentHashMap

Servlet 雖老,但 Spring MVC、Struts、Dubbo HTTP 適配層底層皆基於此。徹底掌握生命周期、線程模型、映射規則,是 Java Web 工程師的內功心法。

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