前言
Servlet 處理 HTTP 交互的核心是 HttpServletRequest (封裝請求) 與 HttpServletResponse (封裝回應)。本文系統整理:繼承體系、核心 API 分類 (狀態碼、標頭、本體)、中文亂碼根因與解決、重定向與轉發、請求參數處理、標頭讀取實戰。
繼承體系
ServletRequest ← HttpServletRequest
ServletResponse ← HttpServletResponse
容器每請求建立新的 Request/Response 物件,傳給 service(req, resp)。
HttpServletResponse 核心 API
狀態碼
| 方法 | 用途 |
setStatus(int sc) | 設定狀態碼 (預設 200) |
sendError(int sc) | 發送錯誤頁面 (404, 500...) |
sendError(int sc, String msg) | 自訂錯誤訊息 |
回應標頭
| 方法 | 用途 |
setHeader(name, value) | 設定單值標頭 (覆蓋同名) |
addHeader(name, value) | 新增多值標頭 (不覆蓋) |
setContentType(type) | 設定 MIME + charset (如 text/html;charset=UTF-8) |
setCharacterEncoding(charset) | 設定字元編碼 (優先級 > setContentType) |
setContentLength(len) | 設定 Content-Length |
sendRedirect(location) | HTTP 302 重定向 (瀏覽器地址列改變) |
回應本體輸出流
getOutputStream():ServletOutputStream,位元組流 (圖片、檔案下載、二進制)。
getWriter():PrintWriter,字元流 (HTML、JSON、文字)。二者互斥,同一請求只能用其一。
中文亂碼根因與徹底解決
亂碼產生鏈路
Java 字串 (Unicode)
→ getWriter() 編碼 (預設 ISO-8859-1, 不支援中文)
→ 位元組流傳輸
→ 瀏覽器解碼 (預設 GBK/UTF-8)
→ 顯示亂碼
解決方案:統一 UTF-8
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// 關鍵:在取得 Writer 前設定
resp.setContentType("text/html;charset=UTF-8");
// 或 resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.println("你好,世界!"); // 正確顯示中文
}
鐵律:setContentType / setCharacterEncoding 必須在 getWriter() / getOutputStream() 之前呼叫。
定時重導向範例
resp.setContentType("text/html;charset=UTF-8");
resp.setHeader("Refresh", "3;url=https://example.com"); // 3 秒後跳轉
resp.getWriter().println("3 秒後自動跳轉...");
HttpServletRequest 核心 API
請求行
| 方法 | 取得內容 |
getMethod() | GET / POST / PUT / DELETE... |
getRequestURI() | /app/servlet/demo (含 context path) |
getRequestURL() | https://host:port/app/servlet/demo |
getQueryString() | 參數字串 (name=value&...) |
getContextPath() | /app (Web 應用根路徑) |
getProtocol() | HTTP/1.1 |
請求標頭
// 取得單一標頭
String ua = req.getHeader("User-Agent");
// 遍歷所有標頭
Enumeration<String> names = req.getHeaderNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
System.out.println(name + ": " + req.getHeader(name));
}
請求參數 (統一處理 GET/POST)
| 方法 | 回傳 | 適用場景 |
getParameter(name) | String (首個值) | 單值參數 |
getParameterValues(name) | String[] (所有值) | 多值參數 (checkbox、multi-select) |
getParameterMap() | Map<String, String[]> | 批次處理、框架綁定 |
getParameterNames() | Enumeration<String> | 遍歷所有參數名 |
注意:POST 表單需在讀取參數前設定 req.setCharacterEncoding("UTF-8"),否則中文參數亂碼。
請求體流 (非表單、JSON、XML、檔案上傳)
getInputStream():位元組流,通用。
getReader():字元流 (依請求編碼解碼),適合 JSON/XML 文字體。
RequestDispatcher:伺服器端轉發與包含
| 方法 | 行為 | 瀏覽器地址列 | 請求物件 |
forward(req, resp) | 轉發給另一資源處理,回應由目標資源產生 | 不變 | 同一個 (可共享屬性) |
include(req, resp) | 包含另一資源輸出到當前回應 | 不變 | 同一個 |
sendRedirect(url) | 重定向 (302),瀏覽器重新發請求 | 改變 | 新請求 (屬性丟失) |
取得 Dispatcher
// 相對當前 Servlet 路徑
RequestDispatcher rd = req.getRequestDispatcher("/target");
// 相對 Web 應用根路徑 (建議)
RequestDispatcher rd = getServletContext().getRequestDispatcher("/target");
rd.forward(req, resp);
總結
掌握 Request/Response 核心 API、編碼鐵律、轉發與重定向差異、參數與標頭處理,是 Servlet 開發與除錯的基本功。現代框架 (Spring MVC) 底層仍委託這組 API,理解本質能更高效排查框架層面的問題。
- 上一篇文章: J2SE 入門:命令列編譯執行第一支 Hello World 完整教學
- 下一篇文章: Java Web Servlet 開發總結 (二):ServletConfig、ServletContext 進階應用與資源存取
Copyright ©
程式碼之家 All Rights Reserved