在 Java Web 開發中,request.getParameter() 與 request.getAttribute() 是兩個極易混淆卻本質截然不同的方法。本文從**使用場景、數據來源、生命週期、類型系統**四個維度徹底釐清二者區別,並給出實戰選型指南。
| 維度 | getParameter() | getAttribute() |
|---|---|---|
| 數據來源 | HTTP 請求參數 (URL Query String、Form 表單體、multipart/form-data) | 伺服器端內部設置 (setAttribute)、Filter/Interceptor 裝飾、框架注入 |
| 數據類型 | 永遠是 String (或 String[]) | 任意 Object (需強轉) |
| 作用範圍 | 整個 HTTP 請求生命週期 (跨 Forward 仍可獲取) | 默認 Request 域 (僅 Forward 有效),可擴展至 Session/Application 域 |
| 寫入方式 | 瀏覽器/客戶端發起請求時自動攜帶,**服務端不可寫入** | 服務端代碼主動調用 setAttribute() 寫入 |
| 典型場景 | 接收用戶提交的表單數據、查詢參數 | 組件間數據傳遞 (Forward)、攜帶業務對象、權限標識、分頁對象 |
getParameter()JSP 表單提交 (welcome.jsp)
<form action="authenticate.jsp" method="post">
請輸入用戶姓名:<input type="text" name="username" />
<input type="submit" value="提交">
</form>
接收頁面 (authenticate.jsp)
<%
// 獲取瀏覽器提交的參數,返回 String
String username = request.getParameter("username");
// 獲取同名多值參數 (如 checkbox),返回 String[]
String[] hobbies = request.getParameterValues("hobby");
%>
歡迎您,<%= username %>
鏈接傳參:authenticate.jsp?username=zhangsan 同樣由 getParameter() 獲取。
setAttribute()/getAttribute()源組件 (authenticate.jsp / Servlet)
<%
String username = request.getParameter("username");
// 將處理後的業務對象放入 Request 域
User user = userService.findByUsername(username);
request.setAttribute("currentUser", user); // Object 類型
// 請求轉發 (地址欄不變)
request.getRequestDispatcher("/hello.jsp").forward(request, response);
%>
目標組件 (hello.jsp)
<%
// 從 Request 域取出,需強轉
User user = (User) request.getAttribute("currentUser");
%>
Hello: <%= user.getName() %>
關鍵點: 僅 **Forward (轉發)** 共享同一 Request 對象,**Redirect (重定向)** 會創建新 Request,**Attribute 丟失**,需改用 Session 或帶參數重定向。
getParameter():Servlet 容器 (Tomcat) 解析 HTTP 協議體,將鍵值對存入內部 Map,getParameter() 只是封裝了 map.get(key)[0]。setAttribute()/getAttribute():Request 對象內部維護一個 Map,開發者自由讀寫,容器**不解析、不干涉**其內容。// Request 域 (默認)
request.setAttribute("key", obj); // 僅當前請求有效,Forward 可傳遞
// Session 域 (跨請求、同用戶)
request.getSession().setAttribute("key", obj); // 30 分鐘默認超時
// Application 域 (全局、全用戶)
getServletContext().setAttribute("key", obj); // 服務器重啟失效
setParameter() 修改參數:不存在該方法,請求參數只讀。若需修改,用 setAttribute() 存新值,或用包裝器 HttpServletRequestWrapper 重寫 getParameter()。getAttribute() 取值為 null:重定向是兩次請求,請改用 session.setAttribute() 或 URL 重寫帶參。getParameter("id") 返回 null 卻確信有值:檢查表單 name="id" 是否正確、enctype 是否為 multipart/form-data (上傳文件需 Commons FileUpload 或 Servlet 3.0 @MultipartConfig 解析)。Parameter — 參數,客戶端來,String 只讀,表單鏈接全靠它。
Attribute — 屬性,服務端造,Object 隨意,Forward 共享最可靠。
Session — 會話,跨請求存,用戶專屬,購物車權限它來管。
Application — 全局,單例共享,配置常量放這裡。
搞清四大域對象 (PageContext、Request、Session、Application) 的生命週期與數據流向,是 Java Web 開發從「能跑通」走向「架構清晰」的分水嶺。