Java Servlet 完整入門:架構原理、部署配置、生命週期、請求處理、轉發重定向與 Session 管理
Servlet 是 Java Web 開發的基石,所有框架(Spring MVC、Struts)底層皆基於 Servlet API。本文系統梳理 Servlet 定義、部署流程、核心生命週期、請求響應處理、轉發與重定向區別、Session 使用,附完整 XML 配置與代碼範例。
一、什麼是 Servlet
- 運行在 Web 容器(Tomcat/Jetty)中的 Java 類,實現
javax.servlet.Servlet 接口(通常繼承 HttpServlet)。
- 接收客戶端 HTTP 請求 → 處理業務邏輯 → 生成動態響應(HTML/JSON/二進制)。
- 類比:Servlet 之於伺服器,如 Applet 之於瀏覽器(已淘汰)。
二、部署四步驟
- 編寫 Servlet 類:繼承
HttpServlet,重寫 doGet/doPost。
- 放置字節碼:
WEB-INF/classes/包名/類名.class。
- 添加依賴:
servlet-api.jar 放入 JDK/jre/lib/ext 或 Tomcat/lib(推薦 Maven 管理)。
- 配置 web.xml:映射 URL 模式到 Servlet 類。
三、web.xml 部署描述符詳解
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee"
version="3.1">
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup> <!-- 啟動時加載 -->
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern> <!-- 訪問路徑:https://host:port/app/hello -->
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout> <!-- 分鐘 -->
</session-config>
</web-app>
四、Servlet 生命週期(核心三方法)
| 階段 | 方法 | 調用時機 | 執行次數 |
| 初始化 | init(ServletConfig config) | 首次請求或啟動時(load-on-startup>0) | 1 次 |
| 服務 | service(req, resp) → 分發 doGet/doPost | 每次客戶端請求 | N 次(多線程) |
| 銷毀 | destroy() | 容器關閉或 Servlet 卸載 | 1 次 |
線程安全警示:Servlet 實例通常為單例,多線程共享實例變量會導致併發問題。請避免使用實例變量存儲請求相關狀態,改用方法局部變量或 ThreadLocal。
五、請求參數獲取與中文處理
// GET 參數:/hello?name=Tom&age=20
String name = request.getParameter("name");
// POST 表單:需先設置編碼(在讀取參數前)
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
六、doGet/doPost 與 service 分發機制
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 處理 GET 請求
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 處理 POST 請求
// 通用邏輯可提取到私有方法,doGet 直接調用 doPost
doGet(req, resp);
}
七、請求轉發 vs 重定向(面試高頻)
| 特性 | 請求轉發 RequestDispatcher.forward() | 重定向 response.sendRedirect() |
| 瀏覽器地址欄 | 不變(原 URL) | 變為目標 URL |
| 請求對象 | 共享同一 request/response | 新請求,原 request 失效 |
| 數據傳遞 | 可用 request.setAttribute() | 需用 Session/參數/URL |
| 跳轉範圍 | 同一 Web 應用內部 | 任意 URL(跨域/外部站點) |
| 速度 | 快(服務端內部) | 慢(經瀏覽器兩次請求) |
| 適用場景 | 登錄校驗失敗跳轉登錄頁、MVC 模式 Controller → View | 登錄成功跳首頁、支付回調、防止表單重複提交 |
// 轉發
RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/views/login.jsp");
rd.forward(request, response);
// 重定向
response.sendRedirect(request.getContextPath() + "/index.jsp");
八、Session 管理
HttpSession session = request.getSession(); // 獲取或創建
session.setAttribute("user", userObj); // 存入對象
User u = (User) session.getAttribute("user"); // 取出需強轉
session.invalidate(); // 註銷(登出)
九、JSP 調用 Servlet 兩種方式
| 方式 | 代碼示例 |
| 表單提交 | <form action="hello?param=value" method="post"> |
| 超鏈接 | <a href="hello?param=value">跳轉</a> |
最佳實踐:現代開發建議使用 Spring MVC(@Controller + @RequestMapping)替代原生 Servlet,享受參數綁定、視圖解析、異常處理、攔截器等豐富功能,僅在極簡項目或學習階段使用原生 Servlet。