JSP HttpServletRequest 請求物件完整指南
HttpServletRequest 封裝客戶端 HTTP 請求。JSP 隱含物件 request 即為其實例,提供取得參數、標頭、Cookie、Session、屬性、輸入流、客戶端資訊等功能。
HTTP 請求結構
GET /search?q=Java&cat=programming HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html,application/xhtml+xml
Accept-Language: zh-TW,zh;q=0.9,en;q=0.8
Cookie: JSESSIONID=abc123; lang=zh-TW
Connection: keep-alive
- 請求行:方法、URL、HTTP 版本
- 請求標頭:Key-Value
- 空行
- 請求主體 (POST/PUT):表單資料、JSON、檔案
核心 API 分類速查
1. 參數取得 (表單、查詢字串)
| 方法 | 回傳 | 說明 |
getParameter(name) | String | 單一值 (多值取首) |
getParameterValues(name) | String[] | 所有值 (checkbox、multi-select) |
getParameterNames() | Enumeration<String> | 所有參數名 |
getParameterMap() | Map<String,String[]> | 完整參數映射 (適合綁定) |
getQueryString() | String | 原始查詢字串 (q=Java&cat=programming) |
2. 標頭資訊
| 方法 | 說明 |
getHeader(name) | 單一標頭值 |
getHeaders(name) | Enumeration (多值標頭) |
getHeaderNames() | 所有標頭名稱 |
getIntHeader(name) | 整數值標頭 |
getDateHeader(name) | 長整數日期值 (毫秒) |
3. Cookie 讀取
| 方法 | 說明 |
getCookies() | Cookie[] 陣列,無則為 null |
4. Session 管理
| 方法 | 說明 |
getSession() | 取得現有或建立新 Session |
getSession(false) | 取得現有,不存在回傳 null |
getRequestedSessionId() | 請求攜帶的 Session ID |
isRequestedSessionIdValid() | Session ID 是否有效 |
isRequestedSessionIdFromCookie() | 是否來自 Cookie |
isRequestedSessionIdFromURL() | 是否來自 URL 重寫 |
5. 請求屬性 (伺服器端暫存資料)
| 方法 | 說明 |
setAttribute(name, obj) | 設定屬性 (Request 範圍) |
getAttribute(name) | 取得屬性 |
removeAttribute(name) | 移除屬性 |
getAttributeNames() | 列舉所有屬性名 |
6. 客戶端與連線資訊
| 方法 | 說明 |
getRemoteAddr() | 客戶端 IP |
getRemoteHost() | 客戶端主機名 (DNS 反解) |
getRemotePort() | 客戶端埠號 |
getLocalAddr() | 伺服器 IP |
getLocalName() | 伺服器主機名 |
getLocalPort() | 伺服器埠號 |
getScheme() | 協定 (http/https) |
isSecure() | 是否 HTTPS |
getServerName() | 伺服器名稱 (Host 標頭) |
getServerPort() | 伺服器埠號 |
7. URL 路徑相關
| 方法 | 說明 | 範例 (請求 https://host:8080/app/search?q=Java) |
getRequestURL() | 完整 URL (不含查詢字串) | https://host:8080/app/search |
getRequestURI() | URI (含 context path) | /app/search |
getContextPath() | Context Path | /app |
getServletPath() | Servlet 映射路徑 | /search |
getPathInfo() | 額外路徑資訊 | /extra/path |
getMethod() | HTTP 方法 | GET |
getProtocol() | 協定版本 | HTTP/1.1 |
8. 輸入流 (讀取原始 Body)
| 方法 | 說明 |
getInputStream() | ServletInputStream (二進位) |
getReader() | BufferedReader (文字,依編碼) |
實作範例
1. 印出所有請求標頭 (除錯用)
<%@ page contentType="text/html;charset=UTF-8" import="java.util.Enumeration" %>
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Request Headers</title></head>
<body>
<h2>請求標頭</h2>
<table border="1"><tr><th>名稱</th><th>值</th></tr>
<%
Enumeration names = request.getHeaderNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
out.println("<tr><td>" + name + "</td><td>" + request.getHeader(name) + "</td></tr>");
}
%>
</table>
</body></html>
2. 取得真實客戶端 IP (反向代理/負載平衡器後)
public String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// X-Forwarded-For 可能包含多個 IP,取第一個
if (ip != null && ip.contains(",")) {
ip = ip.split(",")[0].trim();
}
return ip;
}
3. 讀取 JSON 請求主體 (REST API)
<%@ page import="java.io.*, jakarta.servlet.*" %>
<%
StringBuilder sb = new StringBuilder();
try (BufferedReader br = request.getReader()) {
String line;
while ((line = br.readLine()) != null) sb.append(line);
}
String json = sb.toString(); // {"action":"login","username":"admin"}
// 使用 Jackson/Gson 解析...
%>
4. Request 範圍傳遞資料 (Forward 時)
<%-- Controller Servlet --%>
request.setAttribute("userList", userService.findAll());
request.getRequestDispatcher("/user/list.jsp").forward(request, response);
<%-- list.jsp --%>
<c:forEach items="${userList}" var="u">
<tr><td>${u.name}</td><td>${u.email}</td></tr>
</c:forEach>
中文編碼問題總整理
| 情境 | 問題 | 解決 |
| GET 參數中文亂碼 (Tomcat 8+) | 預設 ISO-8859-1 解碼 | server.xml <Connector URIEncoding="UTF-8"> |
| POST 表單中文亂碼 | 未設定請求編碼 | 讀取參數前 request.setCharacterEncoding("UTF-8") |
| Filter 統一處理 | 所有請求 | EncodingFilter req.setCharacterEncoding("UTF-8") |
常見方法對照表 (JSP 隱含物件 vs Servlet API)
| JSP 隱含物件 | Servlet API 等價 | 範圍 |
request | HttpServletRequest | Request |
session | request.getSession() | Session |
application | getServletContext() | Application |
pageContext | PageContext | Page |
param (EL) | request.getParameter() | 參數 |
header (EL) | request.getHeader() | 標頭 |
cookie (EL) | request.getCookies() | Cookie |
initParam (EL) | getServletContext().getInitParameter() | Context 參數 |