首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

request.getRequestDispatcher() vs response.sendRedirect():轉發與重定向的本質區別、共享數據與地址欄變化全解析

     編輯:Java 相關知識

「轉發」與「重定向」是 Web 開發中最基礎也最易混淆的兩種頁面跳轉方式。本文從 Servlet API 簽名、請求/響應對象共享、瀏覽器地址欄表現、適用場景、路徑解析規則五個維度,建立清晰的心智模型,並給出生產級選擇指南。

一、 核心 API 與對象關係

維度request.getRequestDispatcher() (轉發)response.sendRedirect() (重定向)
方法歸屬 ServletRequest / ServletContext HttpServletResponse
返回類型 RequestDispatcher 對象 無返回值 (void)
核心方法 forward(request, response) sendRedirect(location)
執行位置 服務端內部 客戶端瀏覽器
請求對象 同一個 request(屬性共享) 新 request(屬性丟失)
響應對象 同一個 response 新 response
瀏覽器地址欄 不變(用戶無感知) 變為目標 URL
HTTP 交互 1 次請求/響應 2 次請求/響應(302 + 新請求)
跳轉範圍 僅限當前 Web 應用內部(不可跨域) 任意 URL(可跨域、跨應用、跨協議)
速度 快(無網絡往返) 慢(額外一次網絡往返)

二、 代碼示例對比

1. 轉發

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        String username = req.getParameter("username");
        // 業務邏輯...
        req.setAttribute("user", username); // 設置請求屬性
        
        // 轉發到成功頁,共享 request
        req.getRequestDispatcher("/success.jsp").forward(req, resp);
        // 瀏覽器地址欄仍為 /login
    }
}

2. 重定向

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String username = req.getParameter("username");
        // 業務邏輯...
        
        // 重定向到成功頁,新請求
        resp.sendRedirect(req.getContextPath() + "/success.jsp");
        // 瀏覽器地址欄變為 /success.jsp
        // 原 request 屬性丟失,需用 Session/Flash 屬性/URL 參數傳值
    }
}

三、 路徑解析規則:相對 vs 絕對

API路徑類型解析基準示例
ServletRequest.getRequestDispatcher(path) 相對路徑 / 絕對路徑 當前請求路徑 / Web 應用根路徑 req.getRD("sub.jsp")、req.getRD("/app/sub.jsp")
ServletContext.getRequestDispatcher(path) 只能絕對路徑 Web 應用根路徑 appCtx.getRD("/app/sub.jsp")(相對路徑拋異常)
HttpServletResponse.sendRedirect(path) 相對路徑 / 絕對路徑 / 完整 URL 當前請求 URL / Web 應用根路徑 / 任意 resp.sendRedirect("sub.jsp")、resp.sendRedirect("/app/sub.jsp")、resp.sendRedirect("https://other.com")

最佳實踐:統一使用以 / 開頭的絕對路徑(相對 ContextPath),配合 req.getContextPath() 拼接,避免相對路徑在不同層級 Servlet 下解析錯誤。

四、 選擇決策指南

| 業務場景 | 推薦方式 | 理由 | |----------|----------|------| | 表單提交成功後跳轉結果頁(防止 F5 重複提交) | **重定向** | PRG 模式,瀏覽器地址欄變為 GET 請求,刷新不重複 POST | | 權限校驗失敗跳轉登錄頁 | **重定向** | 地址欄顯示登錄 URL,用戶可收藏/分享;清除請求數據 | | 內部業務流程分步驟處理(Controller → Service → View) | **轉發** | 共享請求數據、單次請求響應、高性能、用戶無感知 | | 錯誤頁面統一處理 (web.xml <error-page>) | **轉發** | 容器內部轉發,保留原請求異常信息 | | 跨應用/跨域跳轉(SSO、支付回調) | **重定向** | 唯一可行方式 | | 下載文件/流式響應 | **無跳轉** | 直接輸出流,設置 Header |

五、 進階:Spring MVC 中的體現

@Controller
public class UserController {
    
    @PostMapping("/login")
    public String login(@RequestParam String username, Model model) {
        // 業務邏輯...
        model.addAttribute("user", username);
        
        // 1. 轉發(默認):返回視圖名,DispatcherServlet 內部 forward
        return "success"; 
        
        // 2. 重定向:redirect: 前綴
        // return "redirect:/success"; // 瀏覽器地址欄變化,model 屬性丟失
        
        // 3. 重定向攜帶參數:RedirectAttributes
        // RedirectAttributes ra = new RedirectAttributes();
        // ra.addFlashAttribute("user", username); // Flash 屬性:存 Session,取後刪
        // return "redirect:/success";
    }
}

六、 總結

轉發 = 服務端內部流轉,共享 request/response,地址欄不變,快,僅限應用內部。
重定向 = 客戶端雙次請求,新 request/response,地址欄變化,慢,支持任意 URL。
掌握 PRG 模式(Post-Redirect-Get)、RedirectAttributes Flash 屬性、路徑解析規則,是構建健壯、用戶友好 Web 應用的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved