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

JSP/Servlet 工作原理深度解析:生命周期、請求處理流程與 MVC 架構定位

     編輯:Java 綜合教學

前言

JSP 和 Servlet 是 Java Web 開發的基石,理解其工作原理對排查問題、優化性能、設計架構至關重要。本文系統梳理 Servlet 生命周期、JSP 編譯執行流程、容器管理機制,並釐清二者在 MVC 中的職責分工。

一、Servlet 生命周期(核心考點)

Servlet 由容器(Tomcat/Jetty/Undertow)全權管理,開發者無法直接實例化。

四大階段

階段觸發時機核心方法執行次數典型工作
1. 加載實例化容器啟動或首次請求構造器1 次創建 Servlet 實例,僅執行一次
2. 初始化實例化後,服務前init(ServletConfig)1 次讀取配置、建立連接池、載入資源
3. 處理請求每次客戶端請求service(req, resp) → doGet/doPostN 次業務邏輯處理,多線程並發執行
4. 銷毀容器關閉/重載/移除destroy()1 次釋放資源、關閉連接、持久化狀態

關鍵特性

  • 單實例多線程:容器默認為每個 Servlet 類創建唯一實例,每請求分配一條線程調用 service()
  • 線程安全責任在開發者:實例變量非線程安全,請勿在 Servlet 類中定義非 final 實例變量存儲請求狀態
  • init/destroy 只執行一次:適合放置昂貴資源初始化/清理邏輯

流程圖解

客戶端請求
    ↓
容器檢查 Servlet 實例是否存在
    ├─ 不存在 → 加載類 → 實例化 → init() → service()
    └─ 存在   → 直接 service()
    ↓
service() 根據 HTTP 方法分發:
    doGet()  /  doPost()  /  doPut()  /  doDelete() ...
    ↓
生成響應返回客戶端

二、JSP 工作原理:本質是 Servlet

核心真相

JSP 最終會被容器翻譯為一個 Servlet 類,然後按 Servlet 生命周期執行。

翻譯編譯流程

階段動作產出觸發條件
1. 翻譯JSP 引擎解析 .jsp 文件Servlet Java 源文件 (*_jsp.java)首次訪問 或 JSP 文件修改後
2. 編譯Java 編譯器編譯源文件字節碼文件 (*_jsp.class)翻譯後自動觸發
3. 載入執行類加載器載入字節碼Servlet 實例編譯成功後
4. 執行調用 service() 處理請求HTML 響應每次請求

Tomcat 實際文件位置

%TOMCAT_HOME%/work/Catalina/localhost/你的項目目錄/org/apache/jsp/
├── index_jsp.java      // 翻譯後的 Servlet 源碼
├── index_jsp.class     // 編譯後的字節碼
└── ...

可直接查看生成的 Java 代碼理解 JSP 標簽/表達式/腳本片段如何轉換為 Servlet 邏輯。

關鍵差異:JSP vs 純 Servlet

維度JSPServlet
本質模板引擎(HTML 為主,嵌入 Java)Java 類(代碼為主,輸出 HTML)
擅長視圖渲染、頁面展示、表單生成請求分發、業務邏輯控制、數據處理
編寫體驗前端友好,設計師可協作純代碼,重構/測試友好
性能首次訪問慢(翻譯編譯),後續同 Servlet啟動即加載,無首次延遲

三、MVC 架構中的職責分工

經典 Model 2 架構 (Struts/Spring MVC 思想雛形)

客戶端請求
    ↓
Controller (Servlet / DispatcherServlet)
    ├─ 接收參數、驗證、綁定
    ├─ 調用 Service 業務邏輯
    ├─ 操作 Model (POJO/DTO/VO)
    └─ 選擇 View (JSP / Thymeleaf / FreeMarker)
    ↓
View 渲染 Model 數據生成 HTML
    ↓
響應客戶端

職責邊界

層技術實現核心職責禁止事項
Controller (C)Servlet / @Controller請求接收、參數校驗、流程控制、視圖選擇業務邏輯、SQL、複雜計算、直接輸出 HTML
Model (M)JavaBean / Entity / DTO / Service / DAO業務邏輯、數據訪問、事務管理、規則引擎HTTP API 依賴、視圖邏輯、請求/響應操作
View (V)JSP / Thymeleaf / Vue/React (前後端分離)數據展示、頁面結構、樣式、用戶交互業務邏輯、數據庫查詢、複雜 Java 代碼

四、容器管理細節(進階)

1. Servlet 加載時機控制

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.demo.MyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>  <!-- 數字越小越優先啟動 -->
</servlet>
  • >=0:容器啟動時實例化並 init()
  • <0 或缺省:首次請求時實例化

2. 多線程並發模型

  • 默認:單實例,請求線程池(Tomcat 默認 200 線程)
  • 實現 SingleThreadModel(已棄用):每請求創建實例,極其低效
  • 現代替代:無狀態 Servlet + ThreadLocal / 請求作用域屬性存儲線程隔離數據

3. JSP 預編譯優化

// Maven 插件預編譯 JSP,構建階段發現語法錯誤,部署時無首次延遲
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <configuration>
        <compileJsp>true</compileJsp>
    </configuration>
</plugin>

五、常見問題與最佳實踐

問題原因解決方案
Servlet 實例變量線程安全多線程共享實例變量無狀態設計:只用局部變量、請求屬性、ThreadLocal
JSP 首次訪問極慢翻譯+編譯耗時預編譯、預熱腳本訪問關鍵頁面
JSP 中大量 Java 代碼違反 MVC 分層遷移到 Controller/Service,JSP 僅用 EL/JSTL/標簽
Servlet 3.0+ 註解不生效web.xml metadata-complete=true設置 metadata-complete="false" 或移除屬性
中文亂碼編碼不一致統一 UTF-8:Filter 設置編碼、JSP pageEncoding、DB 連接串

六、總結

  1. Servlet:容器管理單實例多線程生命周期,核心是 service() 分發 doXxx()
  2. JSP:本質是 Servlet,首次訪問經歷翻譯→編譯→載入→執行
  3. MVC 分工:Servlet 做 Controller(流程控制),JSP 做 View(視圖渲染)
  4. 現代開發:Spring MVC @Controller 替代原生 Servlet,Thymeleaf/Vue 替代 JSP
  5. 理解底層原理是排查類加載、線程安全、性能抖動等疑難雜癥的前提
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved