Servlet 是 Java Web 開發的基石。理解其生命周期管理、請求處理流程與容器交互細節,是排查 Web 層問題、優化性能的前提。
HttpServletRequestweb.xml (或註解) 中的 <servlet-mapping> 匹配 URLinit()HttpServletResponse,調用 service(req, resp)service() 根據 HTTP 方法分發:doGet()/doPost()/…resp.getWriter().write() 或 resp.getOutputStream() 輸出destroy()| 方法 | 調用時機 | 調用次數 | 典型用途 |
|---|---|---|---|
init(ServletConfig) | 首次請求或啟動時 (load-on-startup) | 1 次 | 加載配置、初始化連接池、緩存預熱 |
service(req, resp) | 每次請求 | N 次 | 核心業務處理入口,HTTP 方法分發 |
destroy() | 容器卸載 Servlet 前 | 1 次 | 釋放資源、關閉連接、持久化狀態 |
service()init() 拋異常 → Servlet 標記為不可用,後續請求直接 500
Servlet (Interface)
│
├─ GenericServlet (抽象類)
│ └─ service() 為抽象,需子類實現,協議無關
│
└─ HttpServlet (核心類)
└─ 實現 service():解析 HTTP 方法 → 調用 doGet/doPost/doPut/doDelete...
子類只需覆蓋對應 doXxx() 方法
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
}
| 對象 | 來源 | 核心內容 | 典型用法 |
|---|---|---|---|
| HttpServletRequest | 容器創建 | 請求行、Headers、Parameters、Body、Session、Attributes | getParameter(), getInputStream(), getSession() |
| HttpServletResponse | 容器創建 (空對象) | Status、Headers、Body (Writer/OutputStream) | setContentType(), getWriter(), sendRedirect() |
<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>
/api/user/api/**.do, *.action/ (最低優先級)原則:誰最具體用誰。一個 <servlet> 可映射多個 <servlet-mapping>。
@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 工程師的內功心法。