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

Java Web Servlet 開發總結 (一):核心架構、生命週期、URL 映射與執行緒安全

     編輯:Java 相關知識

前言

本系列系統整理 Servlet 開發核心知識。第一部分涵蓋:Servlet 簡介、運行流程、Eclipse 開發步驟、URL 映射規則、與普通 Java 類差異、load-on-startup、預設 Servlet、執行緒安全問題與解決方案。

Servlet 簡介

  • Sun 定義的介面 javax.servlet.Servlet,開發者實作介面並部署到 Web 容器 (Tomcat/Jetty)。
  • 容器負責實例化、初始化、請求分派、銷毀。
  • 慣例:實作類也稱為 Servlet。

運行流程 (容器視角)

  1. 收到請求 → 解析 URL。
  2. 檢查 Servlet 實例是否存在:
     存在 → 直接第 5 步;
     不存在 → 載入類、實例化、呼叫 init()。
  3. 建立 HttpServletRequest、HttpServletResponse。
  4. 呼叫 service(req, resp)。
  5. 應用停止前呼叫 destroy() 釋放資源。

Eclipse 建立 Servlet 步驟

  1. New → Dynamic Web Project。
  2. 右鍵包 → New → Servlet → 輸入類名、URL 映射。
  3. Eclipse 自動生成類骨架、更新 web.xml (Servlet 3.0+ 可改用註解)。
  4. 啟動 Tomcat → 瀏覽器訪問映射 URL 驗證。

URL 映射詳細規則

基本映射

<servlet>
  <servlet-name>Demo</servlet-name>
  <servlet-class>com.demo.DemoServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Demo</servlet-name>
  <url-pattern>/demo</url-pattern>
</servlet-mapping>

一個 Servlet 可映射多個 <servlet-mapping> (多重 URL)。

通配符映射與優先順序

模式範例優先級
精確路徑/user/profile1 (最高)
目錄通配/user/*2
副檔名通配*.do, *.action3
預設 Servlet/4 (最低)

匹配原則:「誰最長 (最具體) 誰優先」。

多重匹配實例

Servlet1 → /abc/*
Servlet2 → /*
Servlet3 → /abc
Servlet4 → *.do

請求           匹配結果
/abc/a.html    Servlet1 (目錄通配 > 預設)
/abc           Servlet3 (精確 > 目錄通配)
/abc/a.do      Servlet1 (目錄通配 > 副檔名)
/a.do          Servlet2 (預設 > 副檔名)
/xxx/yyy/a.do  Servlet2 (預設 > 副檔名)

Servlet vs 普通 Java 類

load-on-startup 啟動載入

<servlet>
  <servlet-name>InitServlet</servlet-name>
  <servlet-class>com.demo.InitServlet</servlet-class>
  <load-on-startup>1</load-on-startup>  <!-- 正整數,越小越早 -->
</servlet>

用途:啟動時初始化連線池、載入配置、建立資料表、預熱快取。

預設 Servlet

  • 映射 / 的 Servlet 成為預設 Servlet。
  • 處理所有未被其他映射匹配的請求 (靜態資源、404 頁面)。
  • Tomcat 內建 DefaultServlet (映射 /) 處理靜態檔案、目錄列表、歡迎頁。
  • 自訂 / 會覆蓋內建行為,慎用。

執行緒安全:核心陷阱

不安全範例

public class UnsafeServlet extends HttpServlet {
    private int count = 0;  // 實例變數 = 共享狀態
    protected void doGet(...) {
        count++;  // 非原子:讀取、加一、寫回
        resp.getWriter().write("Count: " + count);
    }
}

併發下會丟失更新 (兩執行緒同時讀到 5,寫回 6,預期 7)。

解決方案對比

特性Servlet普通類
啟動方式容器管理 (實例化、初始化、銷毀)new / 靜態方法 / 反射
實例數量單例 (預設),多執行緒共享隨開發者控制
生命週期init → service×N → destroy建構子 → 方法 → GC
執行緒模型每請求一執行緒,共享實例變數無內建模型

SingleThreadModel 已淘汰

Servlet 2.4 標記 Deprecated。容器改建立多實例應對併發,無法解決共享資源 (靜態變數、Session、DB) 的併發問題,且記憶體開銷大。

總結

Servlet 是 Java Web 基石。精通 URL 映射優先順序、單例多執行緒模型、無狀態設計原則,能從根源避開併發 Bug、靈活設計架構、快速定位疑難雜症。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案程式碼評價
區域變數int count = 0; 在方法內✅ 最佳:天然線程安全、無鎖
synchronized(this)synchronized(this){count++;}❌ 序列化所有請求,吞吐暴跌
AtomicIntegerAtomicInteger count = new AtomicInteger();✅ 適用簡單計數
ThreadLocalThreadLocal<Integer> tl = new ThreadLocal<>();⚠️ 隔離執行緒狀態,易洩漏
無狀態設計狀態外移 Redis/DB/Request 屬性✅ 架構級最佳,支援叢集