SpringMVC 返回值類型
(一)核心返回值類型分類
- 視圖渲染類:用于跳轉并渲染頁面,如String(指定視圖名)、ModelAndView(視圖 + 數據)。
- 數據返回類:用于返回數據(而非頁面),如@ResponseBody + Object(返回 JSON/XML 等)、ResponseEntity(自定義響應頭、狀態碼 + 數據)。
- 響應控制類:直接控制響應內容,如void(通過HttpServletResponse手動寫響應)、HttpServletResponse(同上)。
- 異步處理類:用于異步請求處理,如DeferredResult、Callable。
- 重定向專用類:redirect: + RedirectAttributes(重定向時傳遞數據,避免request失效問題)。
- 轉發專用類:forward:(通過String返回值指定轉發路徑)。
(二)返回值選擇指南表格
應用場景 | 推薦返回值類型 | 示例代碼 |
顯示 JSP/Thymeleaf 頁面 | String | return "index";(對應 index.jsp/index.html) |
返回 JSON 數據(接口) | @ResponseBody + Object | @ResponseBody public User getUser() { return user; } |
精確控制響應(頭、狀態碼) | ResponseEntity | return new ResponseEntity<>(data, HttpStatus.OK); |
文件下載 | ResponseEntity<byte[]> 或 void | return new ResponseEntity<>(fileBytes, headers, HttpStatus.OK); |
異步請求處理(如長輪詢) | DeferredResult 或 Callable | public DeferredResult<String> asyncHandle() { ... } |
重定向并傳遞數據 | String + RedirectAttributes | public String redirect(RedirectAttributes attr) { attr.addFlashAttribute("msg", "success"); return "redirect:/index"; } |
服務器內部轉發 | String(帶forward:前綴) | return "forward:/user/detail"; |
直接手動寫響應內容 | void(配合HttpServletResponse) | public void writeResponse(HttpServletResponse response) { response.getWriter().write("hello"); } |
請求轉發(Forward)
(一)基本概念
請求轉發是服務器內部的行為,客戶端僅發起一次請求,服務器在內部將該請求轉發到另一個資源。
(二)工作原理
客戶端 → 請求 → 服務器(Servlet A) → 轉發 → 服務器(Servlet B) → 響應 → 客戶端 |
(三)特點
- URL 不變:瀏覽器地址欄始終顯示原始請求的 URL,不會發生變化。
- 一次請求:整個轉發流程中,客戶端僅發送一次 HTTP 請求。
- 共享 request:轉發前后的資源(如 Servlet、JSP 等)共享同一個request對象,可通過request傳遞數據。
- 服務器內部操作:轉發過程對客戶端透明,客戶端無法感知到服務器內部的轉發行為。
- 范圍限制:僅能轉發到當前應用內部的資源,無法轉發到外部 URL(如其他網站)。
(四)使用場景
- 控制器完成業務邏輯處理后,跳轉到用于數據展示的頁面(如 JSP)。
- 需要在不同資源之間傳遞數據(如從控制器向頁面傳遞查詢結果)時。
- 要求保持瀏覽器地址欄 URL 不變的頁面跳轉場景。
重定向(Redirect)
(一)基本概念
重定向是客戶端的行為,服務器接收到客戶端請求后,會返回一個響應(告知客戶端 “請去訪問另一個 URL”),隨后客戶端會根據該響應發起新的請求。
(二)工作原理
客戶端 → 請求① → 服務器 → 響應(302重定向狀態碼) → 客戶端 → 請求② → 新URL對應的服務器 → 響應 → 客戶端 |
(三)特點
- URL 改變:瀏覽器地址欄會更新為新的目標 URL,顯示最終訪問的地址。
- 兩次請求:客戶端會先后發起兩次 HTTP 請求,第一次請求原始 URL,第二次請求重定向后的 URL。
- 不共享 request:兩次請求分別對應獨立的request對象,無法通過request傳遞數據。
- 無范圍限制:可重定向到任意 URL,包括當前應用內部資源和外部網站(如從自身系統跳轉到百度)。
- 客戶端知情:客戶端能感知到重定向行為(通過地址欄變化或網絡請求記錄)。
(四)使用場景
- 表單提交后(如用戶注冊、登錄提交),防止刷新頁面導致重復提交(即 Post-Redirect-Get 模式)。
- 需要跳轉到外部網站時(如從應用內跳轉到第三方支付平臺)。
- 用戶完成登錄 / 注銷操作后,跳轉到目標頁面(如登錄后跳轉到首頁,注銷后跳轉到登錄頁)。
- 要求改變瀏覽器地址欄 URL 的場景(如優化 URL 顯示,隱藏內部接口路徑)。
請求轉發與重定向對比表格
特性 | 請求轉發(Forward) | 重定向(Redirect) |
請求次數 | 1 次 | 2 次 |
URL 變化 | 不變(顯示原始 URL) | 改變(顯示目標 URL) |
數據共享 | 共享同一個request對象 | 不共享request對象(兩次請求獨立) |
速度 | 較快(僅服務器內部處理,無客戶端往返) | 較慢(需客戶端發起第二次請求,有網絡往返) |
目標范圍 | 僅能跳轉至同一應用內部資源 | 可跳轉至任意 URL(內部 / 外部) |
瀏覽器感知 | 無感知(不知道轉發過程) | 有感知(地址欄變化、可查看兩次請求) |
實現方式(SpringMVC) | return "forward:url" | return "redirect:url" |
實際應用示例(SpringMVC 環境)
(一)請求轉發示例
/*** 返回String類型,實現請求轉發* @return 轉發目標路徑*/@RequestMapping("/save4.do")public String save4() {System.out.println("業務邏輯執行完成(如數據保存)...");// 轉發到/pages目錄下的suc.jsp頁面return "forward:/pages/suc.jsp";}
(二)重定向示例
/*** 返回String類型,實現重定向* @return 重定向目標路徑*/@RequestMapping("/save5.do")public String save5() {System.out.println("業務邏輯執行完成(如表單提交)...");// 重定向到/pages目錄下的suc.jsp頁面return "redirect:/pages/suc.jsp";}
選擇原則
(一)優先選擇請求轉發的場景
- 需保持瀏覽器地址欄 URL 不變時。
- 需在不同資源(如控制器→頁面、控制器→控制器)之間通過request傳遞數據時。
- 僅需跳轉到當前應用內部頁面,且對跳轉性能有較高要求時。
(二)優先選擇重定向的場景
- 表單提交后,需防止刷新頁面導致重復提交時(必選 Post-Redirect-Get 模式)。
- 需跳轉到外部網站(如第三方平臺、合作系統)時。
- 用戶完成登錄、注銷等操作后,需跳轉到目標頁面(如首頁、個人中心)時。
- 需改變瀏覽器地址欄 URL,隱藏內部接口路徑或優化 URL 顯示時。
- 需實現跨應用跳轉(如從 A 應用跳轉到 B 應用)時。