? ? ? ?在 Web 開發中,我們經常需要在不同頁面之間跳轉,比如登錄成功后跳到首頁、提交表單后跳到結果頁面。這時,常見的兩種跳轉方式就是 請求轉發(Request Forward) 和 重定向(Redirect)。
? ? ? ?雖然它們都能實現“頁面跳轉”,但底層原理、適用場景和實現方式都不同。
一、請求轉發(Forward)
1. 定義
請求轉發是服務器內部的一種操作方式,它允許服務器將客戶端請求在服務器內部轉發給另一個資源(如 JSP 或 Servlet)進行處理,而客戶端對轉發行為是“不可見”的。
簡單理解:
用戶發送請求 → 服務器內部轉發 → 返回最終響應給用戶(URL 不變)
2. 工作原理
客戶端發送請求到服務器。
服務器接收請求,并在內部通過
RequestDispatcher
將請求轉發給另一個資源。轉發的資源使用相同的請求對象
request
和響應對象response
。客戶端看到的 URL 不會改變。
3. 使用方式
// Servlet 示例
RequestDispatcher dispatcher = request.getRequestDispatcher("target.jsp");
dispatcher.forward(request, response);
4. 特點
地址欄 URL 不變,對用戶透明。
請求作用域共享,轉發后的資源可以訪問原請求中的數據(如
request.setAttribute()
)。服務器內部操作,效率較高。
不能轉發到其他服務器或不同的域名。
5. 典型場景
登錄成功后,轉發到用戶首頁。
請求處理后將結果展示在 JSP 頁面。
MVC 模式中,Controller 轉發給 View。
6. Java示例
@WebServlet("/login")
public class LoginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");if ("admin".equals(username) && "123".equals(password)) {// 存儲數據到 requestreq.setAttribute("user", username);// 請求轉發到首頁req.getRequestDispatcher("/home.jsp").forward(req, resp);} else {req.setAttribute("msg", "用戶名或密碼錯誤");req.getRequestDispatcher("/login.jsp").forward(req, resp);}}
}
二、重定向(Redirect)
1. 定義
重定向是服務器向客戶端發送一個新的 URL,讓瀏覽器再次發起請求。瀏覽器地址欄會發生變化。
簡單理解:
用戶發送請求 → 服務器返回 302 狀態碼和新 URL → 瀏覽器重新請求新 URL → 返回響應
2. 工作原理
客戶端發送請求到服務器。
服務器通過
response.sendRedirect("新地址")
告訴瀏覽器去請求新的 URL。瀏覽器收到響應后,再次發送請求到新的 URL。
客戶端地址欄發生變化。
3. 使用方式
// Servlet 示例
response.sendRedirect("target.jsp");
4. 特點
地址欄 URL 會改變。
請求作用域不共享,相當于新的請求。
可以重定向到其他網站。
需要客戶端再次發起請求,效率略低于轉發。
5. 典型場景
表單提交后避免重復提交(Post/Redirect/Get 模式)。
登錄成功后跳轉到另一個模塊或不同域的頁面。
頁面重構或網站 URL 改變時進行跳轉。
6. Java示例
@WebServlet("/loginRedirect")
public class LoginRedirectServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");if ("admin".equals(username) && "123".equals(password)) {// 登錄成功后重定向到首頁resp.sendRedirect(req.getContextPath() + "/home.jsp");} else {// 帶參數重定向(URL 拼接)resp.sendRedirect(req.getContextPath() + "/login.jsp?error=1");}}
}
三、請求轉發與重定向的對比
特性 | 請求轉發(Forward) | 重定向(Redirect) |
---|---|---|
URL顯示 | 不變 | 改變 |
請求對象 | 共享 | 不共享,新的請求 |
瀏覽器行為 | 瀏覽器不感知 | 瀏覽器必須發起新請求 |
可跨域 | 否 | 可以 |
性能 | 高(服務器內部操作) | 較低(客戶端需再次請求) |
使用場景 | 內部資源跳轉,如 MVC 轉發 | 表單防重、跨站跳轉 |
四、與安全相關的提示
請求轉發和重定向在實際開發中,需要注意一些安全問題,特別是 SQL 注入 和 開放重定向:
SQL 注入
轉發或重定向本身不會直接導致 SQL 注入,但如果傳遞參數沒有做安全處理,攻擊者可以通過 URL 或表單注入惡意 SQL。
建議:使用 PreparedStatement 或參數化查詢,避免直接拼接 SQL。
開放重定向風險
重定向如果直接使用用戶提供的 URL,可能被攻擊者利用跳轉到惡意網站。
建議:對重定向的 URL 做 白名單校驗,不要直接使用用戶輸入。
五、實用小 Tips
使用轉發傳遞數據
request.setAttribute("msg", "登錄成功");
request.getRequestDispatcher("home.jsp").forward(request, response);
使用重定向避免重復提交
response.sendRedirect("home.jsp");
避免跨站重定向漏洞
String target = request.getParameter("url");
if (target != null && target.startsWith("/app")) {response.sendRedirect(target);
} else {response.sendRedirect("/app/home.jsp");
}
六、總結
請求轉發:服務器內部跳轉,地址欄不變,請求共享,適合內部資源處理。
重定向:客戶端跳轉,地址欄改變,不共享請求,適合防重、跨站跳轉。
安全方面,注意 SQL 注入 和 開放重定向。
? ? ? ?掌握了請求轉發與重定向的原理、使用方式及場景,你就能在 Java Web 開發中更加靈活地處理請求和頁面跳轉。