請求重導向 是伺服器端告知瀏覽器「請去別的 URL 重新發起請求」的機制。瀏覽器收到 302 狀態碼與 Location 標頭後,會自動向新位址發送第二次請求,地址列會顯示新 URL。
@WebServlet("/manualRedirect")
public class ManualRedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 必須同時設定狀態碼與 Location,順序不拘
resp.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); // 302
resp.setHeader("Location", req.getContextPath() + "/login.html");
// 或使用常數:resp.setHeader("Location", "/myapp/login.html");
}
}
@WebServlet("/standardRedirect")
public class StandardRedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 相對路徑:相對於 Context Root
resp.sendRedirect(req.getContextPath() + "/login.jsp");
// 絕對路徑:可導向外部網站
// resp.sendRedirect("https://www.example.com/oauth2/authorize");
// 重要:sendRedirect 後務必 return,避免後續程式碼繼續執行
return;
}
}
| 比較項目 | 重導向 sendRedirect | 轉發 forward |
|---|---|---|
| 請求次數 | 2 次 (Client 發起) | 1 次 (Server 內部) |
| 瀏覽器網址 | 改變 | 不變 |
| Request 共享 | 不可 | 可共享同一 Request 物件 |
| 目標範圍 | 任意 URL (跨域可) | 同一 Web 應用內部資源 |
| 適用場景 | 登入成功跳轉、表單提交後導向、跨應用跳轉 | MVC 架構 Controller → JSP、邏輯分層 |
| 效能 | 稍低 (額外網路往返) | 較高 |
防止表單重複提交的標準模式:
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 處理業務邏輯(驗證、存資料庫...)
boolean success = userService.register(req.getParameter("username"), req.getParameter("password"));
if (success) {
// 2. 重導向到成功頁面 (GET 請求)
// 瀏覽器重新整理不會再次觸發 POST
resp.sendRedirect(req.getContextPath() + "/registerSuccess.jsp");
} else {
// 3. 失敗可轉發回表單頁保留輸入值,或重導向帶錯誤參數
req.setAttribute("error", "註冊失敗");
req.getRequestDispatcher("/register.jsp").forward(req, resp);
}
}
}
req.getContextPath() 組合相對路徑,避免部署路徑變更導致失效。forward() 或輸出內容導致 response committed,再呼叫 sendRedirect() 會拋出 IllegalStateException。URLEncoder.encode(param, "UTF-8")。curl -v https://localhost:8080/app/redirect 查看原始 HTTP 交互。