詳細(xì)聊聊Spring MVC重定向與轉(zhuǎn)發(fā)
重定向和轉(zhuǎn)發(fā)
重定向經(jīng)過客戶端,而轉(zhuǎn)發(fā)沒有,因此相對來說轉(zhuǎn)發(fā)更快速。但有時采用重定向更方便,如:
- 重定向到外部網(wǎng)站;
- 避免用戶重新加載頁面時再次調(diào)用同樣的動作。
return "redirect:/view/"+saveUser.getId();
這里使用重定向來防止當(dāng)前用戶重新加載頁面時'''saveUser'''被二次調(diào)用。
但是使用重定向無法輕松地給目標(biāo)頁面?zhèn)髦?,因此,在Spring3.1后提供了Flash屬性,詳情見后文。
常用處理方式
Controller 視圖方法間的跳轉(zhuǎn),無非就是帶參跳轉(zhuǎn)和不帶參跳轉(zhuǎn)。常用的方法有通過 String 映射 RequestMapping 實(shí)現(xiàn)重定向,或者通過 ModelAndView 對象,又或者是 RedirectView 對象,下面逐一說明。
String 重定向
是 return 映射到另一個 Controller 方法的字符串。如果有請求參數(shù),就拼接在 RequestMapping 映射的字符串后面。
// 返回字符串映射的方式 @RequestMapping("hello") public String hello(HttpServletRequest req, HttpServletResponse resp) { doSomething(); return "redirect:/bye"; // return "redirect:/bye?username=sudoz"; }
ModelAndView 重定向
另一種方法是通過返回 ModelAndView 對象來實(shí)現(xiàn)跳轉(zhuǎn)。類似的,如果有請求參數(shù),也可以通過類似 GET 參數(shù)拼接的方式:
// 返回 ModelAndView 對象 @RequestMapping("hello") public ModelAndView hello(HttpServletRequest req, HttpServletResponse resp) { doSomething(); return new ModelAndView("redirect:/bye"); // return new ModelAndView("redirect:/bye?username=sudoz"); }
RedirectView 重定向
還有一種方法是通過返回 RedirectView 對象實(shí)現(xiàn)跳轉(zhuǎn),該方法和上面的不同之處在于,RedirectView 對象不需要設(shè)置 redirect 前綴:
// 返回 RedirectView 對象 @RequestMapping("hello") public RedirectView hello() { doSomething(); return new RedirectView("/bye"); // return new RedirectView("bye?username=sudoz"); }
帶參跳轉(zhuǎn)
Model在重定向時會丟失攜帶的消息
在做方法跳轉(zhuǎn)時,如果要把參數(shù)帶給下一個方法,像上面代碼里通過拼接 URL 參數(shù)的方法有時候并不實(shí)用。因?yàn)閰?shù)不一定都是是字符串,而且瀏覽器對 URL 的長度是有限制的。RedirectAttributes 對象可以用來保存請求重定向時的參數(shù)。利用 RedirectAttributes 改寫上面的代碼:
@RequestMapping("/") public RedirectView hello(RedirectAttributes attrs) { attrs.addAttribute("message", "hello"); attrs.addFlashAttribute("username", "world"); return new RedirectView("hello"); } @RequestMapping("hello") Map<String, String> hello(@ModelAttribute("message") String meaasge, @ModelAttribute("username") String username) { Map<String, String> map = new HashMap(); map.put("message", message); map.put("username", username); return map; }
上面的代碼中,調(diào)用 addAttribute() 和 addFlashAttribute() 方法往 RedirectAttributes 對象中插入了兩個值,如果看源碼,就能知道,RedirectAttributes 接口的實(shí)現(xiàn)類 RedirectAttributesModelMap 繼承了 ModelMap,本質(zhì)上就是 HashMap 的子類,因此可以用來存儲 Key-Value 對。這兩個方法都很常用,使用上也必然存在不同:
- addAttribute() 方法會把 Key-Value 作為請求參數(shù)添加的 URL 的后面;
- addFlashAttribute() 方法會把 Key-Value 暫存在 session 中,在跳轉(zhuǎn)到目標(biāo)方法后,即完成任務(wù),會從 session 中刪掉;
用 curl 命令來測試:
curl -i http://localhost:8080/ HTTP/1.1 302 Set-Cookie: JSESSIONID=D1CC5E15FA8EF9474C4CED7D4F660E66;path=/;HttpOnly Location: http://localhost:8080/hello;jsessionid=D1CC5E15FA8EF9474C4CED7D4F660E66?username=sudoz Content-Language: en-US Content-Length: 0 Date: Thu, 16 Feb 2017 12:33:46 GMT
可以看到,通過 addAttribute() 添加的鍵值對變成了 URL 后面的參數(shù),addFlashAttribute() 方法添加的鍵值對則沒有出現(xiàn)在 URL 上,而是存儲在了 session 中。跳轉(zhuǎn)的目標(biāo)方法通過 @ModelAttribute("key")注解指定接收的參數(shù)。
redirect 和 forward 的區(qū)別
上面列出的 3 種方法,其實(shí)都是 Spring MVC 在處理請求時的重定向,即 redirect 跳轉(zhuǎn)。另一種分發(fā)請求的方式是轉(zhuǎn)發(fā),即 forward。二者的區(qū)別從 HTTP 的規(guī)范中就明確:
- redirect 的 HTTP 返回碼是 302,且跳轉(zhuǎn)的新 URL 會存儲在 HTTP Response Headers 的 Location 字段中??蛻舳嗽诮邮盏?Response 后,會發(fā)起另一次請求,這次請求的 URL 就是重定向的 URL;
- forward 的轉(zhuǎn)發(fā)過程只發(fā)生在服務(wù)端;Servlet 容器會直接把源請求打向目標(biāo) URL,而不會經(jīng)由客戶端發(fā)起請求;因此客戶端接收到的響應(yīng)是來自轉(zhuǎn)發(fā)后的目標(biāo)方法,但是瀏覽器呈現(xiàn)的 URL 卻并不會改變,且 forward 不能將參數(shù)轉(zhuǎn)發(fā)出去。
附:請求轉(zhuǎn)發(fā)與重定向的區(qū)別圖例
總結(jié)
到此這篇關(guān)于Spring MVC重定向與轉(zhuǎn)發(fā)的文章就介紹到這了,更多相關(guān)Spring MVC重定向與轉(zhuǎn)發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Shiro與Springboot整合開發(fā)的基本步驟過程詳解
這篇文章主要介紹了Shiro與Springboot整合開發(fā)的基本步驟,本文結(jié)合實(shí)例代碼給大家介紹整合過程,感興趣的朋友跟隨小編一起看看吧2023-06-06Sentinel Dashboard限流規(guī)則保存方式
這篇文章主要介紹了Sentinel Dashboard限流規(guī)則保存方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06java 實(shí)現(xiàn)定時的方法及實(shí)例代碼
這篇文章主要介紹了java 定時任務(wù)詳細(xì)介紹及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03SpringBoot項(xiàng)目集成Flyway進(jìn)行數(shù)據(jù)庫版本控制的詳細(xì)教程
這篇文章主要介紹了SpringBoot項(xiàng)目集成Flyway進(jìn)行數(shù)據(jù)庫版本控制,本文分步驟通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07Java數(shù)據(jù)結(jié)構(gòu)優(yōu)先隊(duì)列實(shí)練
通常都把隊(duì)列比喻成排隊(duì)買東西,大家都很守秩序,先排隊(duì)的人就先買東西。但是優(yōu)先隊(duì)列有所不同,它不遵循先進(jìn)先出的規(guī)則,而是根據(jù)隊(duì)列中元素的優(yōu)先權(quán),優(yōu)先權(quán)最大的先被取出,這篇文章主要介紹了java優(yōu)先隊(duì)列的真題,感興趣的朋友一起看看吧2022-07-07