| 特性 | 請求轉發 | 重定向 |
|---|---|---|
| 處理機制 | 容器內部調用,同一請求 | 瀏覽器發起新請求 |
| URL 變化 | 不變 | 變為目標 URL |
| Request 域 | 共享(屬性保留) | 新 Request(原屬性失效) |
| 速度 | 較快 | 較慢(多一次網絡往返) |
| 適用場景 | 同一 Web 應用內部跳轉 | 跨應用、登錄後跳轉、防止表單重復提交 |
// 1. 原始方式
response.setStatus(302);
response.setHeader("Location", "/target");
// 2. 快捷方式(推薦)
response.sendRedirect("/target");
// 3. 額外方式
response.setHeader("Refresh", "0;url=/target");
// 或 JSP 標簽
<c:redirect url="/target"/>
// 1. ServletContext 級別(跨 ServletContext 需配置 crossContext)
getServletContext().getRequestDispatcher("/target").forward(req, resp);
// 2. Request 級別(相對當前路徑)
request.getRequestDispatcher("/target").forward(req, resp);
// 3. PageContext(JSP 頁面中常用)
pageContext.forward("/target");
// 4. JSP 動作標簽
<jsp:forward page="/target"/>
轉發:Client → Servlet A → (容器內部) → Servlet B → Client(一次請求響應)
重定向:Client → Servlet A → (302 + Location) → Client → Servlet B → Client(兩次請求響應)
IllegalStateException。理解這兩者的本質差異,能幫你在設計 Controller 層流程時做出更合理的選擇,避免常見的「Request 屬性丟失」「表單重復提交」等坑。