在 Java Web 開發中,頁面導向是核心功能之一。JSP 與 Servlet 提供了兩種主要的重定向機制:RequestDispatcher.forward()(伺服器端轉發)與 response.sendRedirect()(客戶端重定向)。兩者雖然都能實現頁面跳轉,但運作原理、適用場景與注意事項截然不同。本文將深入剖析這兩大技術,並補充 <jsp:forward>、HTTP Header 修改、Meta Refresh 等進階用法,助你精準選型。
response.sendRedirect() 透過 HTTP 302 狀態碼與 Location 標頭,指示瀏覽器發起新請求。此過程涉及兩次 HTTP 往返:伺服器回應 302 → 瀏覽器解析 Location → 瀏覽器重新請求目標 URL。因此,瀏覽器地址列會更新為新 URL,且原請求的參數、屬性不會自動攜帶。
sendRedirect() 前,不得有任何內容已寫入並送達瀏覽器(含 HTML、空白字元)。雖然現代容器預設啟用 8KB 緩衝區,若未手動 out.flush() 或關閉緩衝,少量輸出通常安全;但最佳實踐是「重定向前零輸出」。return;:重定向動作在頁面處理完畢才生效,後續程式碼仍會執行,可能導致非預期輸出甚至干擾重定向。務必在 sendRedirect() 後立即 return; 終止流程。/target.jsp?id=123),靈活度極高。// Servlet 中
response.setContentType("text/html; charset=UTF-8");
response.sendRedirect("/index.jsp"); // 瀏覽器地址列變為 /index.jsp
return; // 關鍵!
forward() 在容器內部直接將請求與回應物件傳遞給目標資源(JSP、Servlet、HTML),瀏覽器完全無感知,地址列 URL 不變。原請求的所有參數(request.getParameter())與屬性(request.setAttribute())完整保留,效能優於重定向。
?name=value,需改用 request.setAttribute() 傳遞資料。ServletContext sc = getServletContext();
RequestDispatcher rd = sc.getRequestDispatcher("/index.jsp");
rd.forward(request, response); // 瀏覽器地址列維持原樣
底層同樣委派 RequestDispatcher,特性與 forward() 一致。特別警示:若在標籤前已有大量輸出導致緩衝區滿並自動刷新,轉發將失效並拋出 IllegalStateException。此外,轉發後瀏覽器重新整理會重複提交原表單,需配合 PRG 模式避免。
手動設定狀態碼 301(永久移動)或 302(暫時移動)與 Location 標頭,效果等同 sendRedirect(),但可精確控制狀態碼語義:
<%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301
String newLocn = "/newpath/page.jsp";
response.setHeader("Location", newLocn);
%>
<meta http-equiv="refresh" content="5;url=target.html">(5 秒後跳轉)。response.setHeader("Refresh", "5;url=target.html"),更利於動態控制延遲秒數與目標 URL。| 維度 | forward() | sendRedirect() |
|---|---|---|
| 執行位置 | 伺服器端 | 客戶端(瀏覽器) |
| HTTP 交互次數 | 1 次 | 2 次 |
| 瀏覽器地址列 | 不變 | 更新為新 URL |
| Request 參數/屬性 | 完整保留 | 遺失(需查詢字串或 Session 傳遞) |
| 跨域/跨 Context | 不可 | 可 |
| 效能 | 較高 | 較低 |
| 適用場景 | 同應用內流程控制、表單提交後處理 | 登入驗證、跨系統跳轉、需讓用戶看到新 URL |
forward(),效能更好且保留請求資料。sendRedirect()。掌握這些重定向技術的細微差別,能讓你的 Java Web 應用在使用者體驗、效能與架構清晰度上更上一層樓。